4

クリックするとJPopupMenuが表示されるようなボタンを Java で作成したいとします。これを表示するための関連コードはmenu.show(button, button.getWidth()/2, button.getHeight()/2);、以下に示すように、JPopupMenu を左上隅がボタンの中央に表示されるようにするものです。

現在のスイング JPopupMenu

ただし、代わりに、左下隅がボタンの中央にあるようにしたいと思います。これは、iTunes の機能のようです (左下隅の下に+ボタンがあり、左のボタンと同じサイズです)。それの):

ここに画像の説明を入力

JPopupMenu の高さを取得し、ポップアップ メニューが表示されている y 座標に追加することでこれを実現しようとしましたが、JPopupMenu が表示される前に高さが 0 であることがわかりました。コンピューターに表示する場所を伝えようとしているので、助けてください。また、ポップアップ内のアイテムの数が必ずしも同じになるとは限らないため、オフセットをハードコーディングすることはできません。

左下の座標が特定の座標と一致するように、高さが不明な JPopupMenu を表示できるようにするにはどうすればよいですか?

4

3 に答える 3

7

基本的に、これはポップアップ メニューを作成し、 を使用してコンポーネントに登録しますJComponent#setComponentPopupMenu。これは、マウス イベントを監視したり、ポップアップをいつ表示するかを決定したりする必要がなくなったことを意味します。

JComponent#getPopupLocation次に、ポップアップを表示する場所をオーバーライドして計算します。

基本的に、私は を取得しJComponent#getComponentPopupMenu、その優先サイズを取得し、適切なオフセットを計算して、左下隅がコンポーネントの中央に表示されるようにします...

ここに画像の説明を入力

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestPopup02 {

    public static void main(String[] args) {
        new TestPopup02();
    }

    public TestPopup02() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            JPopupMenu menu = new JPopupMenu();
            menu.add(new JMenuItem("Edit Playlist"));
            menu.addSeparator();
            menu.add(new JMenuItem("Check for Available Downloads..."));
            menu.addSeparator();
            menu.add(new JMenuItem("Export..."));
            menu.add(new JMenuItem("Burn Playlist to Disc"));
            menu.add(new JMenuItem("Copy To Play Order"));
            menu.addSeparator();
            menu.add(new JMenuItem("Delete"));
            setComponentPopupMenu(menu);
        }

        @Override
        public Point getPopupLocation(MouseEvent event) {
            // Get the registered popup menu...
            JPopupMenu popup = getComponentPopupMenu();
            // Get the super point, just in case...
            Point pos = super.getPopupLocation(event);
            if (popup != null) {
                // Create a new "point" location
                pos = new Point();
                // get the preferred size of the menu...
                Dimension size = popup.getPreferredSize();
                // Adjust the x position so that the left side of the popup
                // appears at the center of  the component
                pos.x = (getWidth() / 2);
                // Adjust the y position so that the y postion (top corner)
                // is positioned so that the bottom of the popup
                // appears in the center
                pos.y = (getHeight() / 2) - size.height;
            }
            return pos;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Simply draws a cross in the center of the window, so you 
            // know where the center is...
            int width = getWidth() - 1;
            int height = getHeight() - 1;
            g.drawLine(width / 2, 0, width / 2, height);
            g.drawLine(0, height / 2, width, height / 2);
        }

    }
}

Mac出力で更新

ここに画像の説明を入力

ボタンの例

ニーズを正確に満たすソリューションが見つかる可能性はほとんどありません。開発者が開発できる最大のスキルの 1 つは、アイデアを取り入れて必要な形で形にする能力です。

前の例には、必要なものがすべて含まれています。必要なのは、コンセプトからソリューションへと飛躍できることだけです。

getPopupLocationコンポーネントポップアップAPIの一部であるため、メソッドをオーバーライドするか呼び出すことはおそらく必要なものではないでしょう(タスク専用のボタンを持っていない限り、それは悪いことではないかもしれません)ので、適応する必要がありますあなたのニーズへのソリューション...

ここに画像の説明を入力

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestPopup02 {

    public static void main(String[] args) {
        new TestPopup02();
    }

    public TestPopup02() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JButton button;
        private JPopupMenu popup;

        public TestPane() {
            popup = new JPopupMenu();
            popup.add(new JMenuItem("Edit Playlist"));
            popup.addSeparator();
            popup.add(new JMenuItem("Check for Available Downloads..."));
            popup.addSeparator();
            popup.add(new JMenuItem("Export..."));
            popup.add(new JMenuItem("Burn Playlist to Disc"));
            popup.add(new JMenuItem("Copy To Play Order"));
            popup.addSeparator();
            popup.add(new JMenuItem("Delete"));

            setLayout(new GridBagLayout());
            button = new JButton("+");
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    popup.pack();
                    Point pos = new Point();
                    // get the preferred size of the menu...
                    Dimension size = popup.getPreferredSize();
                    // Adjust the x position so that the left side of the popup
                    // appears at the center of  the component
                    pos.x = (button.getWidth() / 2);
                    // Adjust the y position so that the y postion (top corner)
                    // is positioned so that the bottom of the popup
                    // appears in the center
                    pos.y = (button.getHeight() / 2) - size.height;
                    popup.show(button, pos.x, pos.y);
                }
            });
            add(button);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // Simply draws a cross in the center of the window, so you 
            // know where the center is...
            int width = getWidth() - 1;
            int height = getHeight() - 1;
            g.drawLine(width / 2, 0, width / 2, height);
            g.drawLine(0, height / 2, width, height / 2);
        }
    }
}
于 2013-05-10T05:42:17.603 に答える
0

これは実際には私が思っていたよりもずっと簡単で、ほとんどの場合うまくいくはずです。私はあなたのペーストビン コードを使用して、少し遊んでみました。setVisible(true)あなたがフレームを呼び出した後、私は呼び出すことができましたmenu.getPreferredSize()。それを標準出力に出力するだけで、java.awt.Dimension[width=31,height=62]. これは、ActionListener が呼び出される前に実行できるため、高さを利用できます。

メニューで境界線を使用する場合、これを考慮する必要があるかもしれませんが、上記は機能するはずです。

于 2013-05-10T05:05:41.427 に答える