Java 用paintComponent在JApplet中绘制多条连接线
我试图创建一个应用程序,用户可以在画布上画线。用户可以从下拉列表中选择方向并输入线的长度。第一条线从画布的中心开始,下一条线从上一条线结束的地方开始,依此类推-用户可以一条接一条地绘制多条线,并且所有线都连接在一起 我有两个类-TurtleApplet,它使用程序逻辑创建GUI和画布:Java 用paintComponent在JApplet中绘制多条连接线,java,swing,canvas,paintcomponent,japplet,Java,Swing,Canvas,Paintcomponent,Japplet,我试图创建一个应用程序,用户可以在画布上画线。用户可以从下拉列表中选择方向并输入线的长度。第一条线从画布的中心开始,下一条线从上一条线结束的地方开始,依此类推-用户可以一条接一条地绘制多条线,并且所有线都连接在一起 我有两个类-TurtleApplet,它使用程序逻辑创建GUI和画布: public class TurtleApplet extends JApplet implements ActionListener { private JComboBox direction; private
public class TurtleApplet extends JApplet implements ActionListener
{
private JComboBox direction;
private JRadioButton activeButton, passiveButton;
private Button drawButton;
private ButtonGroup group;
private TextField pixels;
private Canvas canvas;
private JPanel panel;
private JPanel panelRadio;
private Button quitPr;
public void init()
{
//directions
String[] directionStrings = { "Right", "Left", "Up", "Down"};
direction = new JComboBox(directionStrings);
//direction.setSelectedIndex(4);
//Buttons
activeButton = new JRadioButton("Aktīvs");
passiveButton = new JRadioButton("Neaktīvs");
quitPr = new Button("Iziet");
//Canvas
canvas = new Canvas();
//canvas.setSize(600, 500);
//canvas.setBackground(Color.red);
canvas.setBorder(BorderFactory.createTitledBorder("Turtle drawing"));
//Panels
panel = new JPanel();
panelRadio =new JPanel();
panel.setLayout(new FlowLayout());
panelRadio.setLayout(new FlowLayout());
//actionListener
activeButton.addActionListener(this);
passiveButton.addActionListener(this);
activeButton.setSelected(true);
quitPr.addActionListener(this);
//Add radiobuttons
group = new ButtonGroup();
group.add(activeButton);
group.add(passiveButton);
//Add Buttons to panel
panelRadio.add(activeButton);
panelRadio.add(passiveButton);
//textfield
pixels = new TextField(12);
//Draw button
drawButton = new Button("Zīmēt");
drawButton.addActionListener(this);
direction.addActionListener(this);
panel.add(panelRadio);
panel.add(pixels);
panel.add(direction);
panel.add(drawButton);
panel.add(quitPr);
getContentPane().add(panel,"North");
getContentPane().add(canvas, "Center");
setSize(650,550);
}
public void actionPerformed( ActionEvent e)
{
if ( e.getSource() == activeButton ) {
drawButton.setVisible(true);
pixels.setEditable(true);
} else if (e.getSource() == passiveButton) {
drawButton.setVisible(false);
pixels.setEditable(false);
} else if(e.getSource() == quitPr){
System.exit(0);
}else if(e.getSource() == drawButton){
int y = Integer.parseInt(pixels.getText());
canvas.addPatt(direction.getSelectedIndex(), Integer.parseInt(pixels.getText()));
repaint();
}
//repaint();
}
}
public class Canvas extends JPanel {
private static final int RIGHT=0, LEFT=1, UP=2, DOWN=3;
public static final int WIDTH=600, HEIGHT=500;
private int direction = 0 ;
private int pixels;
//rivate List points;
public Polygon t = new Polygon();
//public Dimension d = getSize();
public int x = WIDTH/2;
public int y = HEIGHT/2;
public Canvas() {
setSize(WIDTH, HEIGHT);
}
public void addPatt(int pat, int lev) {
direction = pat;
pixels = lev;
}
public void paintComponent(Graphics g) {
switch (direction) {
case LEFT:
drawLineLeft(g, pixels);
break;
case RIGHT:
drawLineRight(g, pixels);
break;
case UP:
drawLineUp(g, pixels);
break;
case DOWN:
drawLineDown(g, pixels);
break;
}
}
private void drawLineLeft(Graphics g, int pix){
if(pix > 0){
g.drawLine(x, y, x-10*pix, y);//left
x =x -10*pix;
}
}
private void drawLineUp(Graphics g, int pix){
if(pix > 0){
g.drawLine(x, y, x, y-10*pix);//up
y = y-10*pix;
}
}
private void drawLineRight(Graphics g, int pix){
if(pix > 0){
g.drawLine(x, y, x+10*pix, y);//right
x = x+10*pix;
}
}
private void drawLineDown(Graphics g, int pix){
if(pix > 0){
g.drawLine(x, y, x, y+10*pix);// down
y = y+10*pix;
}
}
}
小程序可以工作,但问题是在绘制新的行时保存以前的行。当用户输入行的方向和长度并按下按钮时,屏幕上会出现新的行,但前一行会消失。我知道问题出在paintComponent方法上,但我不知道如何准确地更正代码以使所有行可见。有人建议我在数组中存储点坐标,然后在paintComponent中通过数组循环绘制线,但我不知道如何实现这一点。也许有更好的解决方案?正如我在你的案例中所说的,状态就像一个如果不是,你只允许它画一条线。您需要维护一个“行”的列表
,每次调用paintComponent
方法时都可以对其进行迭代
因为一行由多个属性表示,所以最好将该信息封装到一个简单的类或POJO中
public enum Direction {
UP, DOWN, LEFT, RIGHT
}
public class Line {
private Direction direction;
private int length;
public Line(Direction direction, int length) {
this.direction = direction;
this.length = length;
}
public Direction getDirection() {
return direction;
}
public int getLength() {
return length;
}
}
在这里,我将方向属性分离为一个简单的enum
,这允许您在程序的其他地方更容易地引用属性
然后您维护一个列表
的行
s,当调用paintComponent
时,您只需重新迭代并重新绘制
public class Canvas extends JPanel {
public static final int WIDTH = 600, HEIGHT = 500;
public int x = WIDTH / 2;
public int y = HEIGHT / 2;
private List<Line> lines;
public Canvas() {
lines = new ArrayList<>(25);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(WIDTH, HEIGHT);
}
public void addPatt(Direction direction, int length) {
lines.add(new Line(direction, length));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Line line : lines) {
switch (line.getDirection()) {
case UP:
drawLineUp(g, line.getLength());
break;
case DOWN:
drawLineDown(g, line.getLength());
break;
case LEFT:
drawLineLeft(g, line.getLength());
break;
case RIGHT:
drawLineDown(g, line.getLength());
break;
}
}
}
private void drawLineLeft(Graphics g, int pix) {
if (pix > 0) {
g.drawLine(x, y, x - 10 * pix, y);//left
x = x - 10 * pix;
}
}
private void drawLineUp(Graphics g, int pix) {
if (pix > 0) {
g.drawLine(x, y, x, y - 10 * pix);//up
y = y - 10 * pix;
}
}
private void drawLineRight(Graphics g, int pix) {
if (pix > 0) {
g.drawLine(x, y, x + 10 * pix, y);//right
x = x + 10 * pix;
}
}
private void drawLineDown(Graphics g, int pix) {
if (pix > 0) {
g.drawLine(x, y, x, y + 10 * pix);// down
y = y + 10 * pix;
}
}
}
公共类画布扩展了JPanel{
公共静态最终整型宽度=600,高度=500;
公共整数x=宽度/2;
公共int y=高度/2;
私有列表行;
公共画布(){
行=新阵列列表(25);
}
@凌驾
公共维度getPreferredSize(){
返回新尺寸(宽度、高度);
}
公共void addPatt(方向,整数长度){
行。添加(新行(方向、长度));
}
@凌驾
受保护组件(图形g){
超级组件(g);
用于(行:行){
开关(line.getDirection()){
个案:
drawLineUp(g,line.getLength());
打破
按大小写:
drawLineDown(g,line.getLength());
打破
案例左:
drawLineLeft(g,line.getLength());
打破
案例权利:
drawLineDown(g,line.getLength());
打破
}
}
}
专用void drawLineLeft(图形g,整数像素){
如果(pix>0){
g、 抽绳(x,y,x-10*pix,y);//左
x=x-10*pix;
}
}
专用void绘图列表(图形g、int-pix){
如果(pix>0){
g、 抽绳(x,y,x,y-10*pix);//向上
y=y-10*pix;
}
}
专用void drawLineRight(图形g,整数像素){
如果(pix>0){
g、 抽绳(x,y,x+10*pix,y);//右
x=x+10*pix;
}
}
专用空心抽汲线(图形g、int pix){
如果(pix>0){
g、 抽绳(x,y,x,y+10*pix);//向下
y=y+10*pix;
}
}
}
记住,Swing中的绘制是破坏性的,每次调用paintComponent
时,都需要重新绘制组件的整个状态
有关绘画工作原理的更多详细信息,请参见和,正如我在您的中所述,案例
状态类似于一个,否则,您只允许它绘制一条线。您需要维护一个“行”的列表
,每次调用paintComponent
方法时都可以对其进行迭代
因为一行由多个属性表示,所以最好将该信息封装到一个简单的类或POJO中
public enum Direction {
UP, DOWN, LEFT, RIGHT
}
public class Line {
private Direction direction;
private int length;
public Line(Direction direction, int length) {
this.direction = direction;
this.length = length;
}
public Direction getDirection() {
return direction;
}
public int getLength() {
return length;
}
}
在这里,我将方向属性分离为一个简单的enum
,这允许您在程序的其他地方更容易地引用属性
然后您维护一个列表
的行
s,当调用paintComponent
时,您只需重新迭代并重新绘制
public class Canvas extends JPanel {
public static final int WIDTH = 600, HEIGHT = 500;
public int x = WIDTH / 2;
public int y = HEIGHT / 2;
private List<Line> lines;
public Canvas() {
lines = new ArrayList<>(25);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(WIDTH, HEIGHT);
}
public void addPatt(Direction direction, int length) {
lines.add(new Line(direction, length));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Line line : lines) {
switch (line.getDirection()) {
case UP:
drawLineUp(g, line.getLength());
break;
case DOWN:
drawLineDown(g, line.getLength());
break;
case LEFT:
drawLineLeft(g, line.getLength());
break;
case RIGHT:
drawLineDown(g, line.getLength());
break;
}
}
}
private void drawLineLeft(Graphics g, int pix) {
if (pix > 0) {
g.drawLine(x, y, x - 10 * pix, y);//left
x = x - 10 * pix;
}
}
private void drawLineUp(Graphics g, int pix) {
if (pix > 0) {
g.drawLine(x, y, x, y - 10 * pix);//up
y = y - 10 * pix;
}
}
private void drawLineRight(Graphics g, int pix) {
if (pix > 0) {
g.drawLine(x, y, x + 10 * pix, y);//right
x = x + 10 * pix;
}
}
private void drawLineDown(Graphics g, int pix) {
if (pix > 0) {
g.drawLine(x, y, x, y + 10 * pix);// down
y = y + 10 * pix;
}
}
}
公共类画布扩展了JPanel{
公共静态最终整型宽度=600,高度=500;
公共整数x=宽度/2;
公共int y=高度/2;
私有列表行;
公共画布(){
行=新阵列列表(25);
}
@凌驾
公共维度getPreferredSize(){
返回新尺寸(宽度、高度);
}
公共void addPatt(方向,整数长度){
行。添加(新行(方向、长度));
}
@凌驾
受保护组件(图形g){
超级组件(g);
用于(行:行){
开关(line.getDirection()){
个案:
drawLineUp(g,line.getLength());
打破
按大小写:
drawLineDown(g,line.getLength());
打破
案例左:
drawLineLeft(g,line.getLength());
打破
案例权利:
drawLineDown(g,line.getLength());
打破
}
}
}
专用void drawLineLeft(图形g,整数像素){
如果(pix>0){
g、 抽绳(x,y,x-10*pix,y);//左
x=x-10*pix;
}
}
专用void绘图列表(图形g、int-pix){
如果(pix>0){
g、 抽绳(x,y,x,y-10*pix);//向上
y=y-10*pix;
}
}
私人抽绳机