加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java Swing – 将矩形拖到JPanel上的有效方法?

发布时间:2020-12-14 06:08:30 所属栏目:Java 来源:网络整理
导读:我有一些代码来绘制矩形.它用于在JPanel上绘制矩形,以标记小部件的边界.这里代码首先,之后我将解释我的问题cq.题. 首先,我有一个扩展JPanel的类(WidgetDrawingPanel). public WidgetDrawingPanel(int width,int height) { /*To make things visible at least

我有一些代码来绘制矩形.它用于在JPanel上绘制矩形,以标记小部件的边界.这里代码首先,之后我将解释我的问题cq.题.

首先,我有一个扩展JPanel的类(WidgetDrawingPanel).

public WidgetDrawingPanel(int width,int height) {
    /*To make things visible at least*/
    widgets.add(new Widget(10,10,100,WidgetType.TextField));
    widgets.add(new Widget(50,50,200,WidgetType.TextField));
    this.width = width;
    this.height = height;
    this.setBackground(Color.BLUE);
    addListener(); //adds both MouseMotionListener and MouseListener
}

下面你会看到我参考很多.这是一个CoordinateHolder,它保存鼠标移动的开始和当前坐标.

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(Grapics)方法.有循环遍历Widgets,它实际上只是已经绘制的Rects(x,y,w,h属性),但是更多的信息,这在应用程序的绘图部分中没用.每次释放鼠标时,CoordinateHolder都会转换为Widget,并添加到小部件中.

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    System.out.println("Paint");
    g.setColor(Color.BLUE);
    g.fillRect(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.问题

是否有更好的,资源消耗更少的方法,用户可以平滑地拖动矩形?

我读了这个Drag rectangle on JFrame in Java的答案,但那个答案的作者似乎和我一样.但是,再一次,那是不太合适的,对吧?或者计算机是否应该能够轻松地连续重绘组件,这实际上是一种有效的方法吗?

最佳答案
要显示大量不变的背景形状,请将它们绘制到BufferedImage,然后在paintComponent(…)方法中显示BufferedImage.因此,在绘制一个形状时,在paintComponent(…)中绘制它,但是一旦绘制完形状,可能在mouseRelease上绘制,然后在后台BufferedImage中绘制它.

请注意,最能减慢当前绘图代码的是调试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,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,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,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,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,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();
         }
      });
   }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读