Как я могу сделать прозрачным JPopupMenu?

Я хотел бы настроить внешний видJPopupMenu поэтому я сделал пользовательский класс, расширяющий класс JPopupMenu, я переопределилpaintComponent метод, как я сделал бы для любого компонента, который мне нужно настроить.

public class CustomPopupMenu extends JPopupMenu {

    @Override
    public paintComponent(Graphics g) {
        //custom draw
    }
}

Единственная проблема, которую я имею право знать, это то, что яя не в состоянии сделатьJPopupMenu прозрачный. Хотя яsetOpaque(false) было бы достаточно, я был неправ.

Как я могу сделатьJPopupMenu прозрачный?

 nathan09 окт. 2012 г., 19:28
И я нене понимаю смысл вашего комментария. Мне нужно сделать jpopupmenu прозрачным, чтобы нарисовать округленные границы.
 nathan09 окт. 2012 г., 15:41
@mKorbel a jpopupmenu это окно?
 Andrew Thompson09 окт. 2012 г., 18:06
!) Чтоточка сделатьJPopupMenu прозрачный? Если ваш ответ «сделать мое приложение. а "Killer App. "' тогда мой совет - применить свой опыт к вещам, отличным от внешнего вида и ощущения. Потому что это не делаетприложение убийца., 2) Для лучшей помощи, опубликуйтеSSCCE.
 mKorbel09 окт. 2012 г., 16:00
извините, моя бесконечная лень, пожалуйста, смотрите ответ ма здесь :-)
 mKorbel09 окт. 2012 г., 15:28
никогда не пытался, но я никогда не слышал о каких-либо проблем сПрозрачные окна

Ответы на вопрос(4)

Смотрите эту прекрасную статью 2008 годаПолупрозрачные и фасонные поворотные окна Кирилл Гручников.

На основе примеров, приведенных в статье выше, и кода, заимствованного из проекта JGoodies, вы можете установить собственное всплывающее окно Look & Почувствуйте, используя следующие 2 класса:

TranslucentPopup - это настраиваемое всплывающее окно, используемое JPopupMenu:

/**
 * Translucent Popup
 *
 * @author Kirill Grouchnikov [https://www.java.net/pub/au/275]
 */
public class TranslucentPopup extends Popup {
    final JWindow popupWindow;

    TranslucentPopup(Component contents, int ownerX, int ownerY) {
        // create a new heavyweight window
        popupWindow = new JWindow();
        // mark the popup with partial opacity
        com.sun.awt.AWTUtilities.setWindowOpacity(popupWindow, 0.7f);
        // determine the popup location
        popupWindow.setLocation(ownerX, ownerY);
        // add the contents to the popup
        popupWindow.getContentPane().add(contents, BorderLayout.CENTER);
        contents.invalidate();
        JComponent parent = (JComponent) contents.getParent();
        // set a custom border
        parent.setBorder(BorderFactory.createRaisedSoftBevelBorder());
    }

    public void show() {
        popupWindow.setVisible(true);
        popupWindow.pack();
        // mark the window as non-opaque, so that the
        // border pixels take on the per-pixel opacity
        com.sun.awt.AWTUtilities.setWindowOpaque(popupWindow, false);
    }

    public void hide() {
        popupWindow.setVisible(false);
    }
}

TranslucentPopupFactory требуется для установки пользовательского внешнего вида:

/**
 * Translucent Popup Factory
 *
 * @author Kirill Grouchnikov [https://www.java.net/pub/au/275]
 * @author Karsten Lentzsch (JGoodies project)
 */
public class TranslucentPopupFactory extends PopupFactory {
    /**
     * The PopupFactory used before this PopupFactory has been installed in
     * {@code #install}. Used to restored the original state in
     * {@code #uninstall}.
     */
    protected final PopupFactory storedFactory;

    protected TranslucentPopupFactory(PopupFactory originalFactory) {
        storedFactory = originalFactory;
    }

    public Popup getPopup(Component owner, Component contents, int x, int y) throws IllegalArgumentException {
        // A more complete implementation would cache and reuse popups
        return new TranslucentPopup(contents, x, y);
    }

    /**
      * Utility method to install the custom Popup Look and feel.
      * Call this method once during your application start-up.
      *
      * @author Karsten Lentzsch (JGoodies project)
      */
    public static void install() {
        PopupFactory factory = PopupFactory.getSharedInstance();
        if (factory instanceof TranslucentPopupFactory) {
            return;
        }

        PopupFactory.setSharedInstance(new TranslucentPopupFactory(factory));
    }

    /**
      * Utility method to uninstall the custom Popup Look and feel
      * @author Karsten Lentzsch (JGoodies project)
      */
    public static void uninstall() {
        PopupFactory factory = PopupFactory.getSharedInstance();
        if (!(factory instanceof TranslucentPopupFactory)) {
            return;
        }

        PopupFactory stored = ((TranslucentPopupFactory) factory).storedFactory;
        PopupFactory.setSharedInstance(stored);
    }
}

В результате все всплывающие окна (включая JPopupMenu и, возможно, также всплывающие подсказки) теперь будут полупрозрачными и при желании будут иметь собственную границу:

Решение Вопроса

Проблема с всплывающим меню состоит в том, что оно может быть реализовано как контейнер верхнего уровня (Window), и окно непрозрачно, независимо от того, какое значение вы устанавливаете с помощью setOpaque (), оно непрозрачно. Но окна тоже можно сделать прозрачными.

Вы можетемотыга это путем принудительного использования всплывающего окна в тяжелом весе и жестокого изменения его непрозрачности. Попробуйте это как стартовую базу для экспериментов (Java7):

import java.awt.Window;

import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;

public class TranslucentPopup extends JPopupMenu {

    {
        // need to disable that to work
        setLightWeightPopupEnabled(false);
    }

    @Override
    public void setVisible(boolean visible) {
        if (visible == isVisible())
            return;
        super.setVisible(visible);
        if (visible) {
            // attempt to set tranparency
            try {
                Window w = SwingUtilities.getWindowAncestor(this);
                w.setOpacity(0.667F);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

Обратите внимание, что это будетне сделать подменю полупрозрачным!

 kleopatra09 окт. 2012 г., 17:14
для subMenus, сделайте то же самое для пользовательского JMenu: переопределите setPopupMenuVisible и заставьте всплывающее окно 'Окно Ancestor будет прозрачным
 Durandal09 окт. 2012 г., 16:39
Хорошая точка зрения. Я взломал часть отражения, когда я экспериментировал, когда у меня еще не былоположить в setLightWeightPopupEnabled (false), в этот момент я получил эффект, чтородитель окно стало полупрозрачным. Буду обновлять код. Благодарю.
 kleopatra09 окт. 2012 г., 16:36
хм .. почему отражение? SwingUtilities.getWindowAncestor (this) должен быть достаточно хорош, чтобы заполучить содержащее окно

Ты недолжен продлитьJPopupMenu класс, просто сделайте свое меню непрозрачным, а затем сделайтеJMenuItems прозрачный вместо (и непрозрачный).

public class CustomMenuItem extends JMenuItem {
        public void paint(Graphics g) { 
                Graphics2D g2d = (Graphics2D) g.create(); 
                g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f)); 
                super.paint(g2d); 
                g2d.dispose(); 
        } 
}

ИЛИ, сделай наоборот, продлиJPopupMenu сделать его прозрачным и сохранить непрозрачными как меню, так и пункты (таким образом не будет непрозрачной границы меню, как указано выше).

РЕДАКТИРОВАТЬ:

Обратите внимание, что (к сожалению) он не работает, когда всплывающее меню выходит за рамки, как заметил @Durandal.

Хотя вы можете попытаться выполнить некоторые вычисления и изменить местоположение всплывающего окна (при необходимости), чтобы оно всегда оставалось внутри фрейма.

 Durandal09 окт. 2012 г., 16:46
@mKorbel Это относится ки то и другое ты и Ремпелос. Когда всплывающее окно реализовано в тяжелом контейнере (как это должно быть, когда оно не находится в пределах границ окна), всплывающее окно не будет полупрозрачным.
 mKorbel09 окт. 2012 г., 16:38
@Durandal этот комментарий для ??? , добавьте имя пользователя в комментарии :-)
 Rempelos09 окт. 2012 г., 16:19
Протестировано и работает (добавлено изображение)
 Rempelos09 окт. 2012 г., 16:55
@Durandal, достаточно честно, без проблем;)
 Durandal09 окт. 2012 г., 16:18
Вы проверяли это? Было бы удивительно, если бытот работал...
 Rempelos09 окт. 2012 г., 17:34
@kleopatra, вы также можете сделать обратное, расширить JPopupMenu и сделать его непрозрачным. прозрачные вместо пунктов меню, которые будут просто непрозрачными. Возможно, так будет лучше (нет непрозрачной границы меню, как на картинке выше)
 mKorbel09 окт. 2012 г., 16:21
 Rempelos09 окт. 2012 г., 16:47
@Durandal: правда, когда частично за кадром это 'не прозрачный (заметил, что после вашего комментария на самом деле). Но все равно голосовать вниз не было необходимости;)
 Durandal09 окт. 2012 г., 16:54
@Rempelos Don 'принять это лично. Я проголосовал просто потому, что это нея не работаю Под Win Classic, я просто испортил рендеринг для меня, когда я тестировал его (элемент был прозрачным, родительская панель - нет, поэтому он стал более тусклым).
 Durandal09 окт. 2012 г., 16:22
Нет, попробуйте открыть всплывающее окно, чтобы егочастично за пределами рамки. Эпическая. Или поочередно установите значение LightWeightPopupEnabled (false) во всплывающем окне.
 kleopatra09 окт. 2012 г., 17:19
кроме не очень работает, я нене нравится, потому что этос настройками - этона самом деле это не вариант, потому что для этого нужно было бы вручную создавать все элементы, а меню / всплывающее окно обрабатывать создание данного действия.

jpopupmenu это окно?

даJPopup это контейнер, например

код для Java6 (нужно изменить импорт для Java7)

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;

public class TranslucentWindow extends JFrame {

    private static final long serialVersionUID = 1L;
    private JMenuItem m_mniInsertRow;
    private JMenuItem m_mniInsertScrip;
    private JMenuItem m_mniDeleterRow;
    private JMenuItem m_mniDeleteExpiredScrip;
    private JMenuItem m_mniSetAlert;

    public TranslucentWindow() {
        super("Test translucent window");
        setLayout(new FlowLayout());
        add(new JButton("test"));
        add(new JCheckBox("test"));
        add(new JRadioButton("test"));
        add(new JProgressBar(0, 100));
        JPanel panel = new JPanel() {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(400, 300);
            }
            private static final long serialVersionUID = 1L;

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setColor(Color.red);
                g.fillRect(0, 0, getWidth(), getHeight());
            }
        };
        panel.add(new JLabel("Very long textxxxxxxxxxxxxxxxxxxxxx "));
        add(panel);
        final JPopupMenu popupMenu = new JPopupMenu();
        m_mniInsertRow = new JMenuItem("Insert a Row");
        m_mniInsertRow.setOpaque(false);
        m_mniInsertScrip = new JMenuItem("Insert a Scrip");
        m_mniInsertScrip.setOpaque(false);
        m_mniDeleterRow = new JMenuItem("Delete a Row");
        m_mniDeleterRow.setOpaque(false);
        m_mniDeleteExpiredScrip = new JMenuItem("Delete a Expired Scrip");
        m_mniDeleteExpiredScrip.setOpaque(false);
        m_mniSetAlert = new JMenuItem("Set Alert");
        m_mniSetAlert.setOpaque(false);
        popupMenu.add(m_mniInsertRow);
        popupMenu.add(m_mniInsertScrip);
        popupMenu.addSeparator();
        popupMenu.add(m_mniDeleterRow);
        popupMenu.add(m_mniDeleteExpiredScrip);
        popupMenu.add(new JSeparator());
        popupMenu.add(m_mniSetAlert);
        panel.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseReleased(MouseEvent e) {
                if (e.isPopupTrigger()) {
                    int x = e.getX();
                    int y = e.getY();
                    popupMenu.show(e.getComponent(), x, y);
                }
            }
        });
        setSize(new Dimension(400, 300));
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {
        JFrame.setDefaultLookAndFeelDecorated(true);
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                Window w = new TranslucentWindow();
                w.setVisible(true);
                com.sun.awt.AWTUtilities.setWindowOpacity(w, 0.7f);
            }
        });
    }
}

РЕДАКТИРОВАТЬ

интересная поддержкаTranslucency а такжеNimbus L&F, особенноPainter воспроизводить вполне правильноColor (Gradiend тоже при перемещении по экрану), светлая версия с важными изменениями для JPopupMenu, все еще из Java6

образ

из кода

import com.sun.java.swing.Painter;
import java.awt.*;
import javax.swing.*;

public class TranslucentWindow extends JFrame {

    private static final long serialVersionUID = 1L;
    private JPopupMenu popupMenu = new JPopupMenu();
    private JMenuItem m_mniInsertRow = new JMenuItem("Insert a Row");
    private JMenuItem m_mniInsertScrip = new JMenuItem("Delete a Row");
    private JMenuItem m_mniDeleterRow = new JMenuItem("Insert a Scrip");
    private JMenuItem m_mniDeleteExpiredScrip = new JMenuItem("Delete a Expired Scrip");
    private JMenuItem m_mniSetAlert = new JMenuItem("Set Alert");

    public TranslucentWindow() {
        super("Test translucent window");
        setLayout(new FlowLayout());
        add(new JButton("test"));
        add(new JCheckBox("test"));
        add(new JRadioButton("test"));
        add(new JProgressBar(0, 100));
        JPanel panel = new JPanel() {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(400, 300);
            }
            private static final long serialVersionUID = 1L;

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                g.setColor(Color.red);
                g.fillRect(0, 0, getWidth(), getHeight());
            }
        };
        panel.add(new JLabel("Very long textxxxxxxxxxxxxxxxxxxxxx "));
        panel.setComponentPopupMenu(popupMenu);
        add(panel);
        m_mniInsertRow.setOpaque(false);
        m_mniInsertScrip.setOpaque(false);
        m_mniDeleterRow.setOpaque(false);
        m_mniDeleteExpiredScrip.setOpaque(false);
        m_mniSetAlert.setOpaque(false);
        popupMenu.add(m_mniInsertRow);
        popupMenu.add(m_mniInsertScrip);
        popupMenu.addSeparator();
        popupMenu.add(m_mniDeleterRow);
        popupMenu.add(m_mniDeleteExpiredScrip);
        popupMenu.add(new JSeparator());
        popupMenu.add(m_mniSetAlert);
        setSize(new Dimension(400, 300));
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {
        try {
            for (UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    UIManager.getLookAndFeelDefaults().put("nimbusOrange", (new Color(127, 255, 191)));
                    UIManager.getLookAndFeelDefaults().put("PopupMenu[Enabled].backgroundPainter",
                            new FillPainter(new Color(127, 255, 191)));

                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
        } catch (InstantiationException ex) {
        } catch (IllegalAccessException ex) {
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        }
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                Window w = new TranslucentWindow();
                w.setVisible(true);
                com.sun.awt.AWTUtilities.setWindowOpacity(w, 0.7f);
            }
        });
    }

    static class FillPainter implements Painter {

        private final Color color;

        FillPainter(Color c) {
            color = c;
        }

        @Override
        public void paint(Graphics2D g, JComponent object, int width, int height) {
            g.setColor(color);
            g.fillRect(0, 0, width - 1, height - 1);
        }
    }
}
 mKorbel09 окт. 2012 г., 18:26
@kleopatra за ваше бесконечное удовольствие читать "" "правильный""" ответы на этом форуме, яя сделаю это
 nathan10 окт. 2012 г., 09:42
Ницца. Я'Я тоже хотел бы принять это :-)
 kleopatra09 окт. 2012 г., 16:43
Интересно, что всплывающее окно наследует окноs прозрачность (пока его часть не находится за пределами главного окна)
 kleopatra09 окт. 2012 г., 16:45
Кстати: сделайте мне одолжение и отредактируйте код для использования setComponentPopupMenu (вместо открытия на mouseReleased это должно быть запрещено для всего кода!)
 Durandal09 окт. 2012 г., 16:49
@kleopatra Когда всплывающее окно целиком находится внутри окна, оно реализуется как простая JPanel внутри иерархии компонентов Windows. Наткнулся на это, пытаясь взломать мое решение. Если используется setLightWeightPopupEnabled (false), всплывающее окно будет последовательно реализовано в окне. Вероятно, это оптимизация, оставшаяся с первых дней Swing, когда он прославился медлительностью ...
 mKorbel09 окт. 2012 г., 18:52
@Durandal спасибо за ваш вопрос, ежедневное изучение, Nimbus с поддержкой Painter и Translucency на WinXP / Java6, heloooo JavaFX вы меня слышите, еще один год без вас :-)

Ваш ответ на вопрос