使用JPopupMenu + JTextField进行快速搜索 [英] Using JPopupMenu + JTextField for a quick search

查看:71
本文介绍了使用JPopupMenu + JTextField进行快速搜索的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个显示业务数据的JTable.为了使它更有用,我想在右键单击列标题时添加一个弹出菜单,该标题仅显示一个文本输入字段,用作过滤的输入.

I have a JTable that displays business data. To make it more usable, I want to add a popup menu when right-clicking the column header which simply displays a text input field which serves as the input for a filtering.

在列标题上单击鼠标右键并在其中添加JTextField时,很容易添加一个弹出菜单.但是,我希望文本字段自动获得焦点,以便用户可以立即开始键入,而不必首先聚焦文本字段.

It's easy to add a popup menu when right-clicking on the column header and to put a JTextField inside it. However, I would like the text field to automatically gain focus so that the user can instantly start typing rather than having to focus the text field first.

相关代码(在下面可以正常使用的SSCCE):

final JTextField filter = new JTextField( 20 );
final JPopupMenu popup = new JPopupMenu();
popup.add( filter );

table.getTableHeader().addMouseListener( new MouseAdapter() {
    @Override
    public void mousePressed( MouseEvent event ) {
        if( !event.isPopupTrigger() ) {
            return;
        }

        popup.show( table, event.getX(), event.getY() );
        // TODO focus the text field
    }
} );

TODO注释的位置,我尝试了类似filter.requestFocusInWindow()的操作,但这不起作用.我认为弹出菜单本身正在夺走焦点.触发弹出窗口时,如何强制文本字段获得焦点?

At the TODO comment's location I tried things like filter.requestFocusInWindow(), but that doesn't work. I assume that the popup menu itself is stealing the focus. How can I force the text field to gain focus when the popup is triggered?

或者,如果有更好的方法来显示文本字段弹出窗口,我也很高兴看到它:)

Alternatively if there is a better way to display a text field popup I'd be glad to see that, too :)

SSCCE:

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;

public class Test {
    private static final JTable table = new JTable( new Object[][] {
        { "Foo", "Bar" }
    }, new Object[] {
        "A", "B"
    } );

    public static void main( String[] args ) {
        final JTextField filter = new JTextField( 20 );
        final JPopupMenu popup = new JPopupMenu();
        popup.add( filter );

        table.getTableHeader().addMouseListener( new MouseAdapter() {
            @Override
            public void mousePressed( MouseEvent event ) {
                if( !event.isPopupTrigger() ) {
                    return;
                }

                popup.show( table, event.getX(), event.getY() );
                // TODO focus the text field
            }
        } );

        JFrame frame = new JFrame();
        frame.add( new JScrollPane( table ) );
        frame.pack();
        frame.setVisible( true );
    }
}

推荐答案

我使用JOptionPane.showInputDialog()使它工作,但这只是……不舒服.我真的很想弹出一个快捷文本字段.

I get it to work using JOptionPane.showInputDialog(), but that's just… uncomfortable. I'd really like having a quick&easy text field popping up.

不要尝试使用JPopupMenu来实现它,而要使用未修饰的JDialog来实现.它稍微灵活一些,但是需要您说出何时不再需要它,这与JPopupMenu不同.后者并不是真的打算容纳文本字段.

Instead of trying to implement this using JPopupMenu, do it with an undecorated JDialog. It's somewhat more flexible but requires you to say when it is no longer needed, unlike a JPopupMenu. The latter isn't really intended to house text fields.

import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JDialog;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class Test extends JFrame {

    public Test() {

        final JTable table = new JTable(new Object[][]{
            {"Foo", "Bar"}
        }, new Object[]{
            "A", "B"
        });
        final JTextField filter = new JTextField(20);
        final JDialog dialog = new JDialog(this);
        dialog.setLayout(new BorderLayout());
        dialog.setUndecorated(true);
        dialog.add(filter);
        dialog.pack();

        Action hideAction = new HideAction(dialog);
        ActionMap actionMap = filter.getActionMap();
        InputMap inputMap = filter.getInputMap(JComponent.WHEN_FOCUSED);        
        actionMap.put("hideAction", hideAction);
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "hideAction");
        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "hideAction");

        filter.addFocusListener(new FocusAdapter() {

            @Override
            public void focusLost(FocusEvent e) {
                dialog.setVisible(false);
            }

        });

        table.getTableHeader().addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent event) {
                if (!event.isPopupTrigger()) {
                 return;
                }
                showDialog(event);
            }

            @Override
            public void mouseReleased(MouseEvent event) {
                if (!event.isPopupTrigger()) {
                 return;
                }
                showDialog(event);
            }

        private void showDialog(MouseEvent event) {
            Point convertedPoint = SwingUtilities.convertPoint(
                    table.getTableHeader(), event.getPoint(), Test.this);
            Point locationOnScreen = Test.this.getLocationOnScreen();
            locationOnScreen.translate(convertedPoint.x, convertedPoint.y);
            dialog.setLocation(locationOnScreen);
            dialog.setVisible(true);
            // do whatever
        }
        });

        add(new JScrollPane(table));
        pack();
    }

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

            public void run() {
                Test frame = new Test();                
                frame.setVisible(true);
            }
        });

    }

    private static class HideAction extends AbstractAction {

        final JDialog target;

        public HideAction(JDialog target) {
            this.target = target;
        }

        public void actionPerformed(ActionEvent e) {
            target.setVisible(false);
        }
    }
}

六个月后,如果您仍然在寻找答案,就可以了.是的,我很无聊.

这篇关于使用JPopupMenu + JTextField进行快速搜索的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆