Java Swing - Valid approach for dragging rectangles onto a JPanel?
我有一些绘制矩形的代码。它用于在
首先,我有一个扩展
的类 (
1 2 3 4 5 6 7 8 9 | public WidgetDrawingPanel(int width, int height) { /*To make things visible at least*/ widgets.add(new Widget(10,10,100,100, WidgetType.TextField)); widgets.add(new Widget(50,50,100,200, WidgetType.TextField)); this.width = width; this.height = height; this.setBackground(Color.BLUE); addListener(); //adds both MouseMotionListener and MouseListener } |
下面你会看到我引用了很多
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | private void addListener() { this.addMouseMotionListener(new MouseMotionListener() { @Override public void mouseDragged(MouseEvent arg0) { ch.currentX = arg0.getX(); ch.currentY = arg0.getY(); System.out.println("dragging" + ch.currentX +","+ch.currentY); WidgetDrawingPanel.this.repaint(); } }); this.addMouseListener(new MouseListener() { @Override public void mouseReleased(MouseEvent event) { ch.endX = event.getX(); ch.endY = event.getY(); try { checkCoords(); } catch (OutsidePanelException e) { e.printStackTrace(); JOptionPane.showMessageDialog(null,"drawn Outside Panel"); } } @Override public void mousePressed(MouseEvent event) { ch = new CoordinateHolder(event.getX(), event.getY()); } }); } |
,最后是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @Override public void paintComponent(Graphics g) { super.paintComponent(g); System.out.println("Paint"); g.setColor(Color.BLUE); g.fillRect(0, 0, width, height); //making the whole panel blue g.setColor(Color.RED); Graphics2D g2 = (Graphics2D)g; g2.setStroke(new BasicStroke(3)); for (Widget w : widgets) { g.drawRect(w.getX(), w.getY(), w.getW(), w.getH()); } if (ch != null) g.drawRect(ch.startX, ch.startY, ch.currentX - ch.startX, ch.currentY - ch.startY); } |
这段代码可以工作,但我怀疑这是非常低效和低效的,因为上面的代码会在鼠标拖动时不断刷新
问题cq。问题
有没有更好、更省资源的方法,用户可以流畅地拖动矩形?
我在 Java 的 JFrame 上阅读了这个 Drag rectangle 的答案,但该答案的作者似乎和我一样。但是再一次,这太低效了,对吧?或者计算机是否应该能够轻松地不断重绘组件,这实际上是一种有效的方法吗?
要显示大量不变的背景形状,请将它们绘制到 BufferedImage 中,然后在
中绘制它
请注意,最会减慢您当前绘图代码的可能是您的调试 SOP 语句,但我假设这些将从完成的代码中删除。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; import javax.swing.*; @SuppressWarnings("serial") public class DrawingPanel extends JPanel { private static final int PREF_W = 600; private static final int PREF_H = 400; private static final Color DRAWING_COLOR = new Color(255, 100, 200); private static final Color FINAL_DRAWING_COLOR = Color.red; private BufferedImage backgroundImg; private Point startPt = null; private Point endPt = null; private Point currentPt = null; public DrawingPanel() { backgroundImg = new BufferedImage(PREF_W, PREF_H, BufferedImage.TYPE_INT_ARGB); Graphics g = backgroundImg.getGraphics(); g.setColor(Color.blue); g.fillRect(0, 0, PREF_W, PREF_H); g.dispose(); MyMouseAdapter myMouseAdapter = new MyMouseAdapter(); addMouseMotionListener(myMouseAdapter); addMouseListener(myMouseAdapter); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (backgroundImg != null) { g.drawImage(backgroundImg, 0, 0, this); } if (startPt != null && currentPt != null) { g.setColor(DRAWING_COLOR); int x = Math.min(startPt.x, currentPt.x); int y = Math.min(startPt.y, currentPt.y); int width = Math.abs(startPt.x - currentPt.x); int height = Math.abs(startPt.y - currentPt.y); g.drawRect(x, y, width, height); } } @Override public Dimension getPreferredSize() { return new Dimension(PREF_W, PREF_H); } public void drawToBackground() { Graphics g = backgroundImg.getGraphics(); g.setColor(FINAL_DRAWING_COLOR); int x = Math.min(startPt.x, endPt.x); int y = Math.min(startPt.y, endPt.y); int width = Math.abs(startPt.x - endPt.x); int height = Math.abs(startPt.y - endPt.y); g.drawRect(x, y, width, height); g.dispose(); startPt = null; repaint(); } private class MyMouseAdapter extends MouseAdapter { @Override public void mouseDragged(MouseEvent mEvt) { currentPt = mEvt.getPoint(); DrawingPanel.this.repaint(); } @Override public void mouseReleased(MouseEvent mEvt) { endPt = mEvt.getPoint(); currentPt = null; drawToBackground(); } @Override public void mousePressed(MouseEvent mEvt) { startPt = mEvt.getPoint(); } } private static void createAndShowGui() { DrawingPanel mainPanel = new DrawingPanel(); JFrame frame = new JFrame("Drawing Panel"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(mainPanel); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } } |