5

長方形を描画するコードがいくつかあります。に長方形を描画し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していることがわかります。これは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)方法です。loop throughWidgetsがあり、実際には既に描画されていますRects(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れます。すぐに遅くなると思います。特に、ユーザーが大量の四角形を作成する場合 (図 3 に示すように、四角形も継続的に再描画されますpainComponent(Graphics))。

質問cq。問題

ユーザーが四角形をスムーズにドラッグできる、より優れたリソース消費の少ない方法はありますか?

Java の JFrame でこのドラッグ四角形への回答を読みましたが、その回答の作成者は私と同じようにやっているようです。しかし、繰り返しますが、それは非常に非効率的ですよね? または、コンピューターはコンポーネントを継続的に簡単に再描画できるはずであり、これは実際に有効なアプローチですか?

4

1 に答える 1

4

多くの不変の背景形状を表示するには、それらを BufferedImage に描画してから、その BufferedImage をpaintComponent(...)メソッドで表示します。したがって、図形が描画されている間は描画します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, 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();
         }
      });
   }
}
于 2013-03-09T15:08:54.253 に答える