尝试在带有滑块的画布上绘制

huangapple go评论62阅读模式
英文:

Trying to draw on a canvas with sliders

问题

我试图使用滑块(jsliders)允许用户确定在画布上绘制的圆的起点。我使用一个按钮来显示和隐藏这个圆。我在内部的jpanel上使用了绘图(paint)方法,以便绘图不会覆盖组件。然而,在jpanel内部的坐标与整个窗体的坐标不同。所以,对我来说很难获取滑块的坐标,然后将其转化为jpanel的坐标以绘制圆。有没有一种简单的方法可以解决这个问题,而不需要大量的猜测和检查?我还在使用自定义布局miglayout。我已经包括了我的GUI类的代码以及我创建的自定义JPanel的代码,以便我可以处理绘图方法。

public class CircleGUI extends JFrame implements ActionListener {
    // ...(你的代码)

    CircleGUI() {
        initialize();
    }

    private void initialize() {
        // ...(你的代码)

        state = new JButton("显示");
        state.addActionListener(e -> {
            if (!bstate) {
                int positionx = x.getValue() - 80;
                int positiony = y.getValue();
                Color c = colorpick.getColor();
                innerpanel.setColor(c);
                innerpanel.setX(positionx);
                innerpanel.setY(positiony);
                innerpanel.repaint();
                state.setText("隐藏");
                bstate = true;
            } else {
                Color transparent = new Color(0, 0, 0, 0);
                innerpanel.setColor(transparent);
                innerpanel.repaint();
                state.setText("显示");
                bstate = false;
            }
        });
        // ...(你的代码)
    }

    // ...(你的代码)
}

public class CustomPanel extends JPanel implements ActionListener {
    // ...(你的代码)

    public CustomPanel() {
        c = null;
    }

    // ...(你的代码)

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setPaint(c);
        g2.fill(new Ellipse2D.Double(x, y, 100, 100));
    }

    // ...(你的代码)
}

请注意,我将按钮的文本从"Show"和"Hide"分别更改为"显示"和"隐藏",以使其更符合中文。如果你有任何其他问题,或需要进一步的帮助,请随时告诉我。

英文:

I am attempting to use jsliders to allow a user to pinpoint the origin of a circle to be drawn on a canvas. I am using a button to show and hide the circle. I am using paint on an inner jpanel so that paint will not write over components. However, the coordinates inside the jpanel are different than the coordinates for the entire frame. So, it is very difficult for me to get the coordinates of the jslider and then translate it to the jpanel to draw the circle. Is there an easy way to figure this out without a ton of guess and check? I am also using the custom layout miglayout. I have included the code for my GUI class as well as my custom JPanel I made so I could mess with the paint method.

public class CircleGUI extends JFrame implements ActionListener {
private MigLayout layout = new MigLayout();
private CustomPanel innerpanel;
private JSlider x,y;
private JColorChooser colorpick;
private JButton state;
private boolean bstate;
CircleGUI()  {
initialize();
}
private void initialize()  {
Border blackline = BorderFactory.createLineBorder(Color.black);
bstate = false;
x = new JSlider(JSlider.HORIZONTAL,650,325);
x.setPaintTicks(true);
x.setPaintLabels(true);
x.setPreferredSize(new Dimension(650,0));
y = new JSlider(JSlider.HORIZONTAL,650,325);
y.setPaintTicks(true);
y.setPaintLabels(true);
y.setInverted(true);
y.setOrientation(JSlider.VERTICAL);
y.setPreferredSize(new Dimension (0,600));
colorpick = new JColorChooser();
state = new JButton("Show");
state.addActionListener(e -> {
if(!bstate) {
int positionx = x.getValue() - 80;
int positiony = y.getValue();
Color c = colorpick.getColor();
innerpanel.setColor(c);
innerpanel.setX(positionx);
innerpanel.setY(positiony);
innerpanel.repaint();
state.setText("Hide");
bstate = true;
} else {
Color transparent = new Color(0,0,0,0);
innerpanel.setColor(transparent);
innerpanel.repaint();
state.setText("Show");
bstate = false;
}
});
JPanel outerpanel = new JPanel(layout);
innerpanel = new CustomPanel();
innerpanel.setPreferredSize(new Dimension(600,600));
innerpanel.setBorder(blackline);
outerpanel.add(x,"wrap");
outerpanel.add(y,"split 2");
outerpanel.add(innerpanel);
outerpanel.add(state,"wrap");
outerpanel.add(colorpick);
this.setSize(1000, 1000);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(outerpanel);
}
@Override
public void actionPerformed(ActionEvent e) {
}
}
public class CustomPanel extends JPanel implements ActionListener {
private Color c;
private int x;
private int y;
public CustomPanel() {
c = null;
}
@Override
public void actionPerformed (ActionEvent e) {
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(c);
g2.fill(new Ellipse2D.Double(x, y, 100, 100));
}
public void setColor(Color c) {
this.c = c;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
}

答案1

得分: 1

你的问题在于你试图在 JSlider 的值和 CustomPanel 中的坐标之间建立一对一的映射关系。你应该将 JSlider 的值用作百分比,即最小值为零,最大值为100。如果你希望圆圈出现在 CustomPanel 的中间,你应该将两个 JSlider 都放置在它们的中点,即都设置为50%。然后,你可以计算相应维度的50%来获得坐标。如果 CustomPanel 的宽度为600,那么600的50%为300,因此 positionx 需要是300。

我在你的代码中唯一更改的是 positionxpositiony 的计算部分。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.border.Border;

import net.miginfocom.swing.MigLayout;

public class CircleGUI extends JFrame implements ActionListener {
    private MigLayout layout = new MigLayout();
    private CustomPanel innerpanel;
    private JSlider x, y;
    private JColorChooser colorpick;
    private JButton state;
    private boolean bstate;

    CircleGUI() {
        initialize();
    }

    private void initialize() {
        Border blackline = BorderFactory.createLineBorder(Color.black);
        bstate = false;

        x = new JSlider(0, 100, 10);
        x.setPaintTicks(true);
        x.setPaintLabels(true);
        x.setPreferredSize(new Dimension(650, 0));

        y = new JSlider(0, 100, 10);
        y.setPaintTicks(true);
        y.setPaintLabels(true);
        y.setInverted(true);
        y.setOrientation(JSlider.VERTICAL);
        y.setPreferredSize(new Dimension(0, 600));

        colorpick = new JColorChooser();
        state = new JButton("Show");
        state.addActionListener(e -> {
            if (!bstate) {
                int positionx = Math.round(x.getValue() / 100.0f * innerpanel.getSize().width) - 50;
                int positiony = Math.round(y.getValue() / 100.0f * innerpanel.getSize().height) - 50;
                Color c = colorpick.getColor();
                innerpanel.setColor(c);
                innerpanel.setX(positionx);
                innerpanel.setY(positiony);
                innerpanel.repaint();
                state.setText("Hide");
                bstate = true;
            } else {
                Color transparent = new Color(0, 0, 0, 0);
                innerpanel.setColor(transparent);
                innerpanel.repaint();
                state.setText("Show");
                bstate = false;
            }
        });
        JPanel outerpanel = new JPanel(layout);
        innerpanel = new CustomPanel();
        innerpanel.setPreferredSize(new Dimension(600, 600));
        innerpanel.setBorder(blackline);
        outerpanel.add(x, "wrap");
        outerpanel.add(y, "split 2");
        outerpanel.add(innerpanel);
        outerpanel.add(state, "wrap");
        outerpanel.add(colorpick);

        this.setSize(1000, 1000);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.add(outerpanel);
    }

    @Override
    public void actionPerformed(ActionEvent e) {

    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            CircleGUI cg = new CircleGUI();
            cg.setVisible(true);
        });
    }
}

class CustomPanel extends JPanel implements ActionListener {
    private Color c;
    private int x;
    private int y;

    public CustomPanel() {
        c = null;
    }

    @Override
    public void actionPerformed(ActionEvent e) {

    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setPaint(c);
        g2.fill(new Ellipse2D.Double(x, y, 100, 100));
    }

    public void setColor(Color c) {
        this.c = c;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }
}
英文:

Your problem is you are trying to make a one-to-one mapping between the value of the JSlider and the coordinate in your CustomPanel. You should use the JSlider value as a percentage, i.e. minimum value zero and maximum value 100. If you want the circle to appear in the middle of the CustomPanel so you place both JSliders in their mid-points, i.e. both at 50%. Then you calculate 50% of the corresponding dimension to get the coordinate. If the width of CustomPanel is 600, then 50% of 600 is 300 so positionx needs to be 300.

The only thing I changed in your code is the calculation of positionx and positiony.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.border.Border;

import net.miginfocom.swing.MigLayout;

public class CircleGUI extends JFrame implements ActionListener {
    private MigLayout layout = new MigLayout();
    private CustomPanel innerpanel;
    private JSlider x,y;
    private JColorChooser colorpick;
    private JButton state;
    private boolean bstate;

    CircleGUI() {
        initialize();
    }

    private void initialize() {
        Border blackline = BorderFactory.createLineBorder(Color.black);
        bstate = false;

//        x = new JSlider(JSlider.HORIZONTAL, 650, 325);
        x = new JSlider(0, 100, 10);
        x.setPaintTicks(true);
        x.setPaintLabels(true);
        x.setPreferredSize(new Dimension(650, 0));

//        y = new JSlider(JSlider.HORIZONTAL, 650, 325);
        y = new JSlider(0, 100, 10);
        y.setPaintTicks(true);
        y.setPaintLabels(true);
        y.setInverted(true);
        y.setOrientation(JSlider.VERTICAL);
        y.setPreferredSize(new Dimension(0, 600));

        colorpick = new JColorChooser();
        state = new JButton("Show");
        state.addActionListener(e -> {
            if (!bstate) {
                int positionx = Math.round(x.getValue() / 100.0f * innerpanel.getSize().width) - 50;
                int positiony = Math.round(y.getValue() / 100.0f * innerpanel.getSize().height) - 50;
                Color c = colorpick.getColor();
                innerpanel.setColor(c);
                innerpanel.setX(positionx);
                innerpanel.setY(positiony);
                innerpanel.repaint();
                state.setText("Hide");
                bstate = true;
            }
            else {
                Color transparent = new Color(0, 0, 0, 0);
                innerpanel.setColor(transparent);
                innerpanel.repaint();
                state.setText("Show");
                bstate = false;
            }
        });
        JPanel outerpanel = new JPanel(layout);
        innerpanel = new CustomPanel();
        innerpanel.setPreferredSize(new Dimension(600, 600));
        innerpanel.setBorder(blackline);
        outerpanel.add(x, "wrap");
        outerpanel.add(y, "split 2");
        outerpanel.add(innerpanel);
        outerpanel.add(state, "wrap");
        outerpanel.add(colorpick);

        this.setSize(1000, 1000);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.add(outerpanel);
    }

    @Override
    public void actionPerformed(ActionEvent e) {

    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            CircleGUI cg = new CircleGUI();
            cg.setVisible(true);
        });
    }
}

class CustomPanel extends JPanel implements ActionListener {
    private Color c;
    private int x;
    private int y;

    public CustomPanel() {
        c = null;
    }

    @Override
    public void actionPerformed(ActionEvent e) {

    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setPaint(c);
        g2.fill(new Ellipse2D.Double(x, y, 100, 100));
    }

    public void setColor(Color c) {
        this.c = c;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }
}

huangapple
  • 本文由 发表于 2020年9月24日 02:30:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/64034231.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定