在java中制作绘图应用程序的方法更简单?

所以基本上我有一些我几天前工作的代码,有点像Paint,它允许你使用鼠标在屏幕上绘制。 我偶然发现了这个属性,我意识到这是非常低效的,我想知道是否有更实际的方法来做到这一点。 没有任何理由可以提供我的所有代码,但这里是重要的部分

private static void createAndShowGui() { SimpleDraw mainPanel = new SimpleDraw(); MenuBar.createMenuBar(); JLabel label = new JLabel(); label.setText("Drawing prototype 0.0.1"); // label.setHorizontalTextPosition(JLabel.NORTH); label.setFont(new Font("Serif", Font.BOLD, 20)); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(mainPanel); frame.pack(); frame.setLocationByPlatform(true); frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(),BoxLayout.PAGE_AXIS)); frame.setVisible(true); frame.setJMenuBar(MenuBar.getMenuBar()); frame.setBackground(Color.WHITE); frame.add(label); 

上面的代码块设置了jframe(窗口)

  @Override public void mouseDragged(MouseEvent e) { // These console outputs are just so that I know what is happening System.out.println("Event: MOUSE_DRAG"); System.out.println(e.getX()); System.out.println(e.getY()); System.out.println(e.getComponent()); System.out.println(e.getWhen()); System.out.println(e.getButton()); MOUSE_X = e.getX() - 5; //-5 so that the cursor represents the center of the square, not the top left corner. MOUSE_Y = e.getY() - 5; //^ rect = new Rectangle(MOUSE_X, MOUSE_Y, 10, 10 ); //This doesn't ever come into action. repaint(); } 

上面的代码几乎只设置了MOUSE_X和MOUSE_Y变量以及repaint(); 方法

 @Override protected void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; if (rect != null) { if (!colorChoice.equals("Default")) { g2.setColor(Color.BLACK); } switch(colorChoice) { case "GRAY": g2.setColor(Color.GRAY); break; case "CYAN": g2.setColor(Color.CYAN); break; case "BLUE": g2.setColor(Color.BLUE); break; case "RED": g2.setColor(Color.RED); break; case "PINK": g2.setColor(Color.PINK); break; case "YELLOW": g2.setColor(Color.YELLOW); break; case "GREEN": g2.setColor(Color.GREEN); break; case "PURPLE": g2.setColor(Color.MAGENTA); break; case "RESET": g2.setColor(Color.WHITE); case "WHITE": g2.setColor(Color.WHITE); } g2.fillRect(MOUSE_X, MOUSE_Y, 15, 15); if (colorChoice.equals("RESET")) resetColorOnCursor(); } } public static void clearBoard() { tempColor = colorChoice; setColorChoice("RESET"); frame.repaint(); } public static void resetColorOnCursor() { setColorChoice(tempColor); } 

这是我偶然遇到的事情。 当我发现这个时,我试图做的就是在你移动鼠标时基本上跟随光标做一个正方形。 但我忘了输入代码部分paintComponent(g); ,这使这个程序变成了我原本想要的东西。 这部分的底部部分基本上是我如何清除董事会。 我100%确定这不是清除/重置这样的帧的正确方法,但我找不到另一种方法。 如果有人有任何提示或更好的方法来正确地做到这一点,我将非常感激。 谢谢! :d

您当前的方法基本上是通过不调用super.paintComponent打破绘制链的要求。 paintComponent方法执行一组操作,您没有接管这些操作,这可能会导致一些非常奇怪的绘制工件难以一致地复制。

Graphics是一个共享资源,因此用于绘制其他控件的Graphics上下文将与用于绘制组件的相同,除非您事先“清理”上下文,之前绘制到上下文的内容将保留(这就是为什么你的代码目前“似乎”工作)。

相反,您应该使用MouseListener来定义一个锚点,它表示按下鼠标的点,然后使用MouseMotionListener来定义选择区域的范围,例如……

油漆选择

 import java.awt.AlphaComposite; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class SelectExample { public static void main(String[] args) { new SelectExample(); } public SelectExample() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { private Rectangle selection; public TestPane() { MouseAdapter ma = new MouseAdapter() { private Point clickPoint; @Override public void mousePressed(MouseEvent e) { clickPoint = e.getPoint(); selection = null; } @Override public void mouseDragged(MouseEvent e) { Point dragPoint = e.getPoint(); int x = Math.min(clickPoint.x, dragPoint.x); int y = Math.min(clickPoint.y, dragPoint.y); int width = Math.max(clickPoint.x, dragPoint.x) - x; int height = Math.max(clickPoint.y, dragPoint.y) - y; if (selection == null) { selection = new Rectangle(x, y, width, height); } else { selection.setBounds(x, y, width, height); } repaint(); } @Override public void mouseReleased(MouseEvent e) { selection = null; repaint(); } }; addMouseListener(ma); addMouseMotionListener(ma); } @Override public Dimension getPreferredSize() { return new Dimension(200, 200); } protected void paintComponent(Graphics g) { super.paintComponent(g); if (selection != null) { g.setColor(UIManager.getColor("List.selectionBackground")); Graphics2D g2d = (Graphics2D) g.create(); g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f)); g2d.fill(selection); g2d.dispose(); g2d = (Graphics2D) g.create(); g2d.draw(selection); g2d.dispose(); } } } } 

只是为了突出你将面临的问题,如果你继续违反paintComponent方法的要求,这就是当我不调用super.paintComponent时会发生的事情

违反

我只是将两个JButton添加到JFrame (因此甚至不直接添加到面板中)。 paintComponent完成了一系列重要的工作,你忽略了这些工作,这会导致更多的问题和问题。

自由格式线示例…

自由forms线实际上是一种幻觉,它是在一系列点之间绘制的一系列(小)线,原因是因为MouseListener不会报告它移动的每个鼠标位置,具体取决于鼠标的速度。移动了,你可能会收到很多回电或一些。

因此,我们不是绘制只绘制点,而是将点存储在List并在它们之间绘制线条,例如……

自由形式

 import java.awt.AlphaComposite; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class FreeFormLines { public static void main(String[] args) { new FreeFormLines(); } public FreeFormLines() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class TestPane extends JPanel { private List> points; public TestPane() { points = new ArrayList<>(25); MouseAdapter ma = new MouseAdapter() { private List currentPath; @Override public void mousePressed(MouseEvent e) { currentPath = new ArrayList<>(25); currentPath.add(e.getPoint()); points.add(currentPath); } @Override public void mouseDragged(MouseEvent e) { Point dragPoint = e.getPoint(); currentPath.add(dragPoint); repaint(); } @Override public void mouseReleased(MouseEvent e) { currentPath = null; } }; addMouseListener(ma); addMouseMotionListener(ma); } @Override public Dimension getPreferredSize() { return new Dimension(200, 200); } protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); for (List path : points) { Point from = null; for (Point p : path) { if (from != null) { g2d.drawLine(from.x, from.y, px, py); } from = p; } } g2d.dispose(); } } }