簡體   English   中英

獲取 Swing 組件相對於屏幕的 position

[英]Getting the position of a Swing Component relative to the screen

我有一個名為SuggestionField的 class 它將向用戶顯示一個項目列表以自動完成他的輸入。 他讓輸入顯示在 JDialog( suggestionFrame ) 中。 我需要將 JDialogs position 設置為低於其父級,但我無法獲得相對於屏幕的父級( JTextField )X 和 Y。

問題示例

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Arrays;

public class Runner {
    public static void main(String[] args) {

        JFrame frame = new JFrame();
        String[] items = new String[]{"Tiger", "Wolf", "Car", "Cat", "Space", "Sing", "Scene"};
        SuggestionField suggestionField = new SuggestionField(new ArrayList<>(Arrays.asList(items)), frame);

        frame.setDefaultCloseOperation(3);
        frame.setSize(100, 65);
        frame.setLocationRelativeTo(null);

        JPanel panel = new JPanel();

        panel.setLayout(new GridLayout(1,1));
        panel.add(suggestionField);

        frame.add(panel);

        frame.setVisible(true);

    }


    public static class SuggestionField extends JTextField implements DocumentListener, KeyListener {

        String[] values = new String[0];
        ArrayList<String> displayValues = new ArrayList<>(0);
        JDialog suggestionFrame;
        JPanel suggestionPanel = new JPanel();
        Color backGround = new Color(109, 104, 104, 133);
        Color selectBackGround = new Color(109, 104, 104, 133);
        Color textColor = new Color(5, 19, 88, 255);
        Color selectTextColor = new Color(115, 134, 238, 255);
        BoxLayout bl = new BoxLayout(suggestionPanel, BoxLayout.Y_AXIS);
        int selectedEntry = 0;

        public SuggestionField(ArrayList<String> values, JFrame parentDisplay) {
            this.getDocument().addDocumentListener(this);
            this.addKeyListener(this);
            suggestionFrame = new JDialog(parentDisplay);
            suggestionFrame.add(suggestionPanel);
            suggestionFrame.setUndecorated(true);
            suggestionFrame.setAlwaysOnTop(true);
            suggestionFrame.setFocusable(false);
            suggestionPanel.setFocusable(false);
            bl.maximumLayoutSize(suggestionPanel);
            this.values = values.toArray(this.values).clone();
        }

        public boolean updateSuggestions() {
            boolean added = false;
            boolean add;
            displayValues.clear();
            for (int i = 0;i < values.length;i++) {
                add = true;
                for (int k = 0;k < this.getText().length() && k < values[i].length();k++) {
                    if (values[i].toUpperCase().charAt(k) != this.getText().toUpperCase().charAt(k)) {
                        add = false;
                        break;
                    }
                }
                if (add && !values[i].equalsIgnoreCase(this.getText()) && values[i].length() > this.getText().length()) {
                    added = true;
                    displayValues.add(values[i]);
                }
            }
            return added;
        }

        private void updateDisplay() {

            suggestionFrame.setSize(this.getWidth(), 16 * displayValues.size());
            suggestionPanel.removeAll();
            suggestionPanel.setLayout(new BoxLayout(suggestionPanel, BoxLayout.Y_AXIS));
            for (int i = 0;i < displayValues.size();i++) {
                JLabel a = new JLabel(displayValues.get(i));
                if (i == selectedEntry) {
                    a.setBackground(selectBackGround);
                    a.setForeground(selectTextColor);
                } else {
                    a.setBackground(backGround);
                    a.setForeground(textColor);
                }
                suggestionPanel.add(a);
            }
            suggestionPanel.revalidate();
            suggestionFrame.revalidate();
            suggestionFrame.setLocation(this.getX(), this.getY() + this.getHeight());
            suggestionFrame.setVisible(true);
        }

        @Override
        public void insertUpdate(DocumentEvent e) {
            if (updateSuggestions()) {
                updateDisplay();
            } else suggestionFrame.setVisible(false);
            selectedEntry = 0;
            this.requestFocus();
        }

        @Override
        public void removeUpdate(DocumentEvent e) {
            if (updateSuggestions()) {
                updateDisplay();
            } else suggestionFrame.setVisible(false);
            selectedEntry = 0;
            this.requestFocus();
        }

        @Override
        public void changedUpdate(DocumentEvent e) {

        }

        @Override
        public void keyTyped(KeyEvent e) {

        }

        @Override
        public void keyPressed(KeyEvent e) {
            int ID = e.getKeyCode();
            switch (ID) {

                case 40:
                    if (selectedEntry < displayValues.size() - 1) selectedEntry++;
                    updateDisplay();
                    break;

                case 38:
                    if (selectedEntry > 0) selectedEntry--;
                    updateDisplay();
                    break;

                case 10:
                    this.setText(displayValues.get(selectedEntry));
                    break;

                case 27:
                    suggestionFrame.setVisible(false);
                    break;

            }
            this.requestFocus();
            this.grabFocus();
        }

        @Override
        public void keyReleased(KeyEvent e) {

        }

    }
}

有什么方法可以在updateDisplay() (第 97 行)方法中獲得JTextField的絕對suggestionFrame

您可以使用SwingUtilities.convertPointToScreen來執行此操作。

只需傳遞 (x, y+height) 和您的輸入字段即可獲取顯示下拉列表的起點。

    JButton component = new JButton();
    Point pt = new Point(component.getLocation());
    pt.y += component.getHeight();
    SwingUtilities.convertPointToScreen(pt, component);

    // pt is now in screen coords... so you can use it to position the pop-up

完整的文檔可以在這里找到: https://docs.oracle.com/javase/7/docs/api/javax/swing/SwingUtilities.ZFC35FDC70D5FC69D2693EZZ5A

我需要將 JDialogs position 設置為低於其父級..

使用Window.setLocationRelativeTo(Component)

這只會將 JDialog 放在 JTextFiled 的頂部

實際上,它比這更微妙。 例如,它將考慮對話框是否會離開屏幕,然后將其重新打開。 如果將 position 基於“屏幕上的位置”,則需要明確處理這一點。

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM