JavaSwing—将矩形拖动到JPanel上的有效方法?
我有一些画矩形的代码。它用于在JavaSwing—将矩形拖动到JPanel上的有效方法?,java,swing,user-interface,drawing,Java,Swing,User Interface,Drawing,我有一些画矩形的代码。它用于在JPanel上绘制矩形,以标记小部件的边界。这里首先是代码,然后我将解释我的问题cq。问题 首先,我有一个类(WidgetDrawingPanel),它扩展了JPanel public WidgetDrawingPanel(int width, int height) { /*To make things visible at least*/ widgets.add(new Widget(10,10,100,100, WidgetType.TextF
JPanel
上绘制矩形,以标记小部件的边界。这里首先是代码,然后我将解释我的问题cq。问题
首先,我有一个类(WidgetDrawingPanel
),它扩展了JPanel
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
}
下面你会看到我引用了很多ch
。这是一个坐标文件夹
,它保存鼠标移动的起始坐标和当前坐标
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());
}
});
}
最后是paintComponent(graphics)
方法。有循环通过小部件
,它们实际上刚刚绘制了矩形(x,y,w,h属性),但是它包含了更多的信息,在应用程序的绘制部分不有用。每次释放鼠标时,CoordinateHolder
将转换为小部件,并添加到widgets
@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);
}
这段代码正在工作,但我怀疑这是非常低效和性能不佳的,因为上面的代码在鼠标拖动时不断刷新JPanel
,也就是说,每10毫秒刷新一次?我想它很快就会变慢,尤其是当用户创建大量矩形时(这些矩形也会不断地重新绘制,如painComponent(Graphics)
中所示)
问题cq。问题
是否有一种更好、资源消耗更少的方法,用户可以平滑地拖动矩形
我读了一个答案,但这个答案的作者似乎和我一样。但同样,这是一种表现,对吗?或者计算机应该能够很容易地连续地重新绘制组件,这实际上是一种有效的方法吗?要显示大量不变的背景形状,请将它们绘制到BuffereImage,然后在paintComponent(…)
方法中显示该BuffereImage。因此,在绘制形状时,请在paintComponent(…)
中绘制它,但一旦绘制完形状,请使用鼠标轻松地在背景缓冲区图像中绘制它
请注意,使当前绘图代码最慢的可能是调试SOP语句,但我假设这些语句将从完成的代码中删除
例如:
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();
}
});
}
}
谢谢,我将很快检查BuffereImage,但可能需要一段时间,因为我很忙。你的假设是正确的,很好的例子。即使通过RDP,这也会顺利进行。我想我可以把它用于我的目的。远程桌面协议。我是远程登录的。