2

ジム/ランニングからの統計をログに記録する、私自身の使用のためのロギング ツールをまとめ始めたところです。swing/awt での唯一の経験は、Graphics2D オブジェクトを完全に制御でき、そうでないゲームのアクティブ レンダリングです。オーバーライドされたペイントを使用してスイング コンポーネントを実装することに依存します。

とにかく、パネルの 1 つに追加できるダミーの JComponent を作成したいと考えていました (このパネルは、オプションを使用して別のサイドパネルから選択したものに応じて、グラフィック、統計などを表示します)。前述のパネルを使用し、マウスドラッグで選択用の四角形を描画して、より高い解像度が存在する場合にデータを拡大できるようにします。方法がわかりません。コンポーネントをパネルに追加しましたが、パネル内には何も登録されません。代わりに、パネル/フレームの下部に限定されたローカル スペースがあるようです。

ここにコンポーネントがあります

package gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JComponent;

@SuppressWarnings("serial")
public class MarkerRectangle extends JComponent implements MouseListener,
        MouseMotionListener {

private boolean draw;
private int startX, endX, startY, endY;
private Color color = new Color(0, 255, 0, 100);

public MarkerRectangle(int width, int height) {
    setPreferredSize(new Dimension(width, height));
    this.addMouseListener(this);
    this.addMouseMotionListener(this);
}

@Override
public void mouseClicked(MouseEvent e) {
    System.out.println("Mouse clicked@ " + e.getX() + "," + e.getY());
}

@Override
public void mouseEntered(MouseEvent e) {
    System.out.println("Mouse entered @ " + e.getX() + "," + e.getY());

}

@Override
public void mouseExited(MouseEvent e) {
    System.out.println("Mouse left @ " + e.getX() + "," + e.getY());
}

@Override
public void mousePressed(MouseEvent e) {
    System.out.println("Mouse pressed@ " + e.getX() + "," + e.getY());
}

@Override
public void mouseReleased(MouseEvent e) {
    System.out.println("Mouse was released @ " + e.getX() + "," + e.getY());
}

@Override
public void mouseDragged(MouseEvent e) {
    System.out.println("Mouse being dragged, currently@ " + e.getX() + ","
            + e.getY());

}

@Override
public void mouseMoved(MouseEvent e) {
    System.out.println("I registered a move@ " + e.getX() + "," + e.getY());
}

@Override
// Draw rectangle
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g.create();
    g2d.dispose();
}

}

パネル_

public class GraphPane extends JPanel {


public GraphPane(Graph graph) {
    this.add(graph);
    this.add(new MarkerRectangle(800, 600));
    this.setBackground(Color.gray);
    this.setPreferredSize(new Dimension(800, 600));
}


}

グラフには、ランダム データ atm が保持されます

public class Graph extends JComponent {
private GeneralPath data;
private Stroke stroke;

public Graph() {
    this.data = new GeneralPath();
    this.stroke = new BasicStroke(3f);
    this.setPreferredSize(new Dimension(750, 550));
    init();
}

private void init() {
    data.moveTo(0, 0);
    double cntr = 0;
    double[][] points = new double[10][1];
    for (double[] point : points) {
        cntr += 100;
        point[0] = Math.random() * 100;
        point[1] = Math.random() * 100;
        data.lineTo(cntr, point[1]);
    }
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g.create();
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    g2d.setStroke(stroke);
    g2d.draw(data);
    g2d.dispose();
}
}

上記のようなものを実装したいのは、最終的には GUI が非常に複雑になり、データをマークするための四角形を描画するような単純なイベントになると想像するためです (多くの if テストとコードの乱雑さを防ぐため)。 )。

私が得るもののスクリーンショット: ここに画像の説明を入力

私が欲しいもの: ここに画像の説明を入力

編集 以下の受け入れられた回答はより良い解決策ですが、誰かがそれを使用したい場合に備えてこれを投稿しています。preferredSize より小さいサイズに変更すると機能しません。

public class Test {

public static void main(String[] args) {
    GeneralJFrame frame = new GeneralJFrame(1200, 800);
    frame.addPanel(new GraphPane(new Graph()), BorderLayout.CENTER);
    frame.addPanel(new ButtonPane(), BorderLayout.SOUTH);
    frame.addPanel(new ButtonPane(), BorderLayout.SOUTH);
    frame.addPanel(new ButtonPane(), BorderLayout.WEST);
    frame.addPanel(new ButtonPane(), BorderLayout.EAST);
    frame.addPanel(new ButtonPane(), BorderLayout.NORTH);
    frame.start();
}
}

public class GraphPane extends JPanel {


public GraphPane(Graph graph) {
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = GridBagConstraints.REMAINDER;
    c.gridheight = GridBagConstraints.REMAINDER;
    c.gridx = 0;
    c.gridy = 0;
    this.setLayout(new GridBagLayout());
    this.add(graph);
    this.add(new MarkerRectangle(), c);
    this.setBackground(new Color(205, 201, 201));
}



}

public class MarkerRectangle extends JComponent implements MouseListener,
    MouseMotionListener {

private boolean draw;
private int startX, endX, startY, endY;

public MarkerRectangle() {
    this.addMouseListener(this);
    this.addMouseMotionListener(this);
    setOpaque(false);
    setPreferredSize(new Dimension(800, 600));
}

@Override
public void mouseClicked(MouseEvent e) {

}

@Override
public void mouseEntered(MouseEvent e) {

}

@Override
public void mouseExited(MouseEvent e) {

}

@Override
public void mousePressed(MouseEvent e) {
    startX = e.getX();
    startY = e.getY();
    draw = true;
}

@Override
public void mouseReleased(MouseEvent e) {
    draw = false;
    repaint();
}

@Override
public void mouseDragged(MouseEvent e) {
    endX = e.getX();
    endY = e.getY();
    repaint();
}

@Override
public void mouseMoved(MouseEvent e) {

}

@Override
// Draw rectangle
protected void paintComponent(Graphics g) {
    System.out.println(getSize());
    if (!draw)
        return;
    int w = endX-startX;
    int h = endY - startY;
    Graphics2D g2d = (Graphics2D) g.create();
    g2d.setColor(new Color(255, 165, 0));
    g2d.fillRect(startX, startY, w, h);
    g2d.dispose();
}

}

public class ButtonPane extends JPanel {
public ButtonPane() {
    add(new JButton("HELLO"));
    setBackground(Color.gray);
    setBorder(BorderFactory.createEtchedBorder(Color.white,
            Color.gray.darker()));
}
}

public class GeneralJFrame {
private JFrame frame;

public GeneralJFrame(int width, int height) {
    this.frame = new JFrame("Le Muscles");
    this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public void addPanel(JPanel panel, String location) {
    this.frame.add(panel, location);
}

public void start() {
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}
}

出力: (オレンジ色はマウスでドラッグ) ここに画像の説明を入力

4

1 に答える 1

2

私はまだあなたの質問を完全には理解していません。私が見る限り、あなたは

  • いくつかの JPanel を作成しました
  • 1 つの JPanel に MouseListener と MouseMotionListener がある場合
  • その JPanel を別の JPanel の下部に追加しました。
  • 一番下にあるJPanelは、指示されたとおりにすべてのマウスイベントを登録します
  • したがって、プログラムはコードに基づいて期待どおりに動作しています。

  • 私が持っている質問はこれです: 期待どおりに動作しないのはなぜですか?

  • MouseListeners と MouseMotionListeners がアタッチされた JPanel を追加すると、GUI のすべての JPanel がリッスンされると予想される場合は、もちろんそうはなりません。より多くの GUI でマウス イベントを登録するには、これらのコンポーネントに MouseListeners と MouseMotionListeners を追加する必要があります。そして、それが私が見ているあなたの質問に対するこれまでの私の答えです。あなたが現在直面している本当の質問に私が答えていない場合は、私たちのためにそれを明確にしてください.

あなたは次のように述べています:

私が欲しいのは、上のスクリーンショットの青いパネルの上にある目に見えない(透明な)パネルで、下にあるサブパネルではなく、青いパネルと同じ大きさです。青いものにこれを含めたいです(これは単なる jcomponent であるため、問題にはなりません)。私が達成したいのは、マウスイベントを登録する「見えない」オーバーレイの並べ替えであるため、これらのイベントを青いパネルに実装する必要はありません。

これには JLayer の使用を検討してください。JLayer API によると:

JLayer は、複合コンポーネントに対してカスタム ペイントを実行するか、そのサブコンポーネントからの入力イベントをキャッチするだけでよい場合に適したソリューションです。


OK、私はそれを少し試してみて、次のようなものを思いつきました:

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Path2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Random;

import javax.swing.*;
import javax.swing.plaf.LayerUI;

@SuppressWarnings("serial")
public class GraphPane2 extends JPanel {
   private static final int GRAPH_WIDTH = 1000;
   private static final int GRAPH_HEIGHT = 750;
   private Graph2 graph2 = new Graph2(GRAPH_WIDTH, GRAPH_HEIGHT);

   public GraphPane2() {
      LayerUI<Graph2> myLayerUI = new MyLayerUI<Graph2>();
      JLayer<Graph2> panelLayer = new JLayer<Graph2>(graph2, myLayerUI);
      setLayout(new BorderLayout());
      add(panelLayer);

      myLayerUI.addPropertyChangeListener(new PropertyChangeListener() {

         @Override
         public void propertyChange(PropertyChangeEvent evt) {
            if (MyLayerUI.MOUSE_RELEASED.equals(evt.getPropertyName())) {
               Rectangle rect = (Rectangle) evt.getNewValue();
               System.out.println(rect);
            }
         }
      });
   }

   private static void createAndShowGui() {
      GraphPane2 mainPanel = new GraphPane2();

      JFrame frame = new JFrame("Graph Pane2");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.setResizable(false);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

@SuppressWarnings("serial")
class MyLayerUI<V extends JComponent> extends LayerUI<V> {
   private static final Color FILL_COLOR = new Color(0, 128, 0, 128);
   public static final String MOUSE_RELEASED = "mouse released";
   private Point pressedPt;
   private Point draggedPt;
   private Rectangle rect;

   @Override
   public void paint(Graphics g, JComponent c) {
      super.paint(g, c);
      if (rect != null) {
         Graphics2D g2 = (Graphics2D) g;
         g2.setColor(FILL_COLOR);
         g2.fill(rect);
      }
   }

   public void installUI(JComponent c) {
      super.installUI(c);
      ((JLayer) c).setLayerEventMask(AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK);
   }

   public void uninstallUI(JComponent c) {
      super.uninstallUI(c);
      ((JLayer)c).setLayerEventMask(0);
   }

   @Override
   public void eventDispatched(AWTEvent e, JLayer<? extends V> l) {
      MouseEvent mEvt = (MouseEvent) e;
      int id = mEvt.getID();
      int btn = mEvt.getButton();
      if (id == MouseEvent.MOUSE_PRESSED && btn == MouseEvent.BUTTON1) {
         pressedPt = mEvt.getPoint();
         rect = new Rectangle(pressedPt.x, pressedPt.y, 0, 0);
      }
      if (id == MouseEvent.MOUSE_PRESSED && btn != MouseEvent.BUTTON1) {
         pressedPt = null;
      }
      if (id == MouseEvent.MOUSE_DRAGGED && pressedPt != null) {
         draggedPt = mEvt.getPoint();
         int x = Math.min(draggedPt.x, pressedPt.x);
         int y = Math.min(draggedPt.y, pressedPt.y);
         int width = Math.abs(draggedPt.x - pressedPt.x);
         int height = Math.abs(draggedPt.y - pressedPt.y);
         rect = new Rectangle(x, y, width, height);
      }
      if (id == MouseEvent.MOUSE_RELEASED && pressedPt != null) {
         draggedPt = mEvt.getPoint();
         int x = Math.min(draggedPt.x, pressedPt.x);
         int y = Math.min(draggedPt.y, pressedPt.y);
         int width = Math.abs(draggedPt.x - pressedPt.x);
         int height = Math.abs(draggedPt.y - pressedPt.y);
         rect = new Rectangle(x, y, width, height);
         firePropertyChange(MOUSE_RELEASED, null, rect);
      }      
      l.repaint();
   }
}

@SuppressWarnings("serial")
class Graph2 extends JPanel {
   private static final int MAX_DATA_POINTS = 100;
   private static final int STEP = 10;
   private static final Stroke STROKE = new BasicStroke(3f);
   private Path2D path2D;
   private int width;
   private int height;
   private int[] data = new int[MAX_DATA_POINTS + 1];
   private Random random = new Random();

   public Graph2(int width, int height) {
      this.width = width;
      this.height = height;
      init();

      addComponentListener(new ComponentAdapter() {
         @Override
         public void componentResized(ComponentEvent e) {
            path2D = new Path2D.Double();
            int w = getWidth();
            int h = getHeight();
            double x = 0;
            double y = ((double) MAX_DATA_POINTS - data[0]) * h
                  / MAX_DATA_POINTS;
            path2D.moveTo(x, y);
            for (int i = 1; i < data.length; i++) {
               x = (i * w) / (double) MAX_DATA_POINTS;
               y = ((double) MAX_DATA_POINTS - data[i]) * h
                     / (double) MAX_DATA_POINTS;
               path2D.lineTo(x, y);
            }
         }
      });
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(width, height);
   }

   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (path2D != null) {
         Graphics2D g2d = (Graphics2D) g;
         g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
               RenderingHints.VALUE_ANTIALIAS_ON);
         g2d.setStroke(STROKE);
         g2d.draw(path2D);
      }
   };

   private void init() {
      // create and fill random data
      data[0] = 0;
      boolean up = true;
      // max and min data values -- used for normalization
      int min = Integer.MAX_VALUE;
      int max = Integer.MIN_VALUE;
      for (int i = 1; i < data.length; i++) {
         up = random.nextInt(4) < 3 ? up : !up;
         if (up) {
            data[i] = data[i - 1] + random.nextInt(STEP);
         } else {
            data[i] = data[i - 1] - random.nextInt(STEP);
         }

         if (data[i] > max) {
            max = data[i];
         }
         if (data[i] < min) {
            min = data[i];
         }
      }

      // normalize the data
      for (int i = 0; i < data.length; i++) {
         int datum = (MAX_DATA_POINTS * (data[i] - min)) / (max - min);
         data[i] = datum;
      }

   }
}

これは次のようになります。

ここに画像の説明を入力

于 2013-04-28T00:47:39.930 に答える