选项卡在 JRadioButtons 上停止工作,但 shift + tab 仍然有效

Tabs stop working on JRadioButtons but shift + tab still do

提问人:tumorito 提问时间:11/14/2023 最后编辑:tumorito 更新时间:11/14/2023 访问量:55

问:

我设置了 Tab 键顺序(使用 swing builder 自动创建类本身)。它运行良好,直到它进入 JRadioButtons,它们位于 ButtonGroup 中(我认为这是问题仍然存在的地方)。一旦它进入那里,选项卡就不再起作用(当它应该转到 numPersons 时),但 shift+tab 确实可以正常工作(去酒店)。setFocusTraversalPolicy(new FocusTraversalOnArray(new Component[]{hotel, individual, multiple, numPersons, accept, cancel, exit}));

下面是 UI 的图片,以便进一步说明:enter image description here

下面是 Swing 生成器创建的类 FocusTraversalOnArray:

/*******************************************************************************
 * Copyright (c) 2011, 2023 Google, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Google, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.wb.swing;

import java.awt.Component;
import java.awt.Container;
import java.awt.FocusTraversalPolicy;

/**
 * Cyclic focus traversal policy based on array of components.
 * <p>
 * This class may be freely distributed as part of any application or plugin.
 * 
 * @author scheglov_ke
 */
public class FocusTraversalOnArray extends FocusTraversalPolicy {
    private final Component m_Components[];
    ////////////////////////////////////////////////////////////////////////////
    //
    // Constructor
    //
    ////////////////////////////////////////////////////////////////////////////
    public FocusTraversalOnArray(Component components[]) {
        m_Components = components;
    }
    ////////////////////////////////////////////////////////////////////////////
    //
    // Utilities
    //
    ////////////////////////////////////////////////////////////////////////////
    private int indexCycle(int index, int delta) {
        int size = m_Components.length;
        int next = (index + delta + size) % size;
        return next;
    }
    private Component cycle(Component currentComponent, int delta) {
        int index = -1;
        loop : for (int i = 0; i < m_Components.length; i++) {
            Component component = m_Components[i];
            for (Component c = currentComponent; c != null; c = c.getParent()) {
                if (component == c) {
                    index = i;
                    break loop;
                }
            }
        }
        // try to find enabled component in "delta" direction
        int initialIndex = index;
        while (true) {
            int newIndex = indexCycle(index, delta);
            if (newIndex == initialIndex) {
                break;
            }
            index = newIndex;
            //
            Component component = m_Components[newIndex];
            if (component.isEnabled() && component.isVisible() && component.isFocusable()) {
                return component;
            }
        }
        // not found
        return currentComponent;
    }
    ////////////////////////////////////////////////////////////////////////////
    //
    // FocusTraversalPolicy
    //
    ////////////////////////////////////////////////////////////////////////////
    public Component getComponentAfter(Container container, Component component) {
        return cycle(component, 1);
    }
    public Component getComponentBefore(Container container, Component component) {
        return cycle(component, -1);
    }
    public Component getFirstComponent(Container container) {
        return m_Components[0];
    }
    public Component getLastComponent(Container container) {
        return m_Components[m_Components.length - 1];
    }
    public Component getDefaultComponent(Container container) {
        return getFirstComponent(container);
    }
}

这里还有一个简单的类来重新创建我所说的内容(它有更多功能,我改变了它,使其变得简单,但它只是为了重新创建选项卡问题):


import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;

import org.eclipse.wb.swing.FocusTraversalOnArray;

public class ReservaStack extends JDialog implements ActionListener , MouseListener, MouseMotionListener, FocusListener {

    private static final long serialVersionUID = 1L;
    private JPanel contentPane;
    private JPanel panel;
    private JButton exit;
    
    private JCheckBox hotel;
    private JLabel hotelLbl;
    private JRadioButton individual;
    private JRadioButton doble;
    private JRadioButton multiple;
    private JTextField numPersonas;
    private JButton accept;
    private JButton cancel;
    private final ButtonGroup habitacionTipo = new ButtonGroup();
    
    int yMouse;
    int xMouse;
    
    /*
     * Launch application
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    ReservaStack frame = new ReservaStack();
                    frame.setVisible(true);
                    frame.setLocationRelativeTo(null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    
    /**
     * Create the frame.
     */
    public ReservaStack() {
        setResizable(false);
        setUndecorated(true);
        setModal(true);
        setBounds(100, 100, 600, 400);
        contentPane = new JPanel();
        contentPane.setBackground(new Color(255, 255, 255));
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));

        setContentPane(contentPane);
        contentPane.setLayout(null);
        
        panel = new JPanel();
        panel.addMouseListener(this);
        panel.addMouseMotionListener(this);
        panel.setBackground(new Color(255, 255, 255));
        panel.setBounds(0, 0, 600, 33);
        contentPane.add(panel);
        panel.setLayout(null);
        
        exit = new JButton("X");
        exit.addActionListener(this);
        exit.addMouseListener(this);
        exit.addFocusListener(this);
        exit.setFont(new Font("Tahoma", Font.PLAIN, 16));
        exit.setBorder(null);
        exit.setFocusPainted(false);
        exit.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        exit.setContentAreaFilled(false);
        exit.setBounds(0, 0, 63, 33);
        panel.add(exit);
        
        JLabel reserva = new JLabel("BOOK");
        reserva.setHorizontalAlignment(SwingConstants.CENTER);
        reserva.setFont(new Font("Cascadia Code", Font.BOLD, 20));
        reserva.setForeground(new Color(255, 255, 255));
        reserva.setOpaque(true);
        reserva.setBackground(new Color(0, 64, 128));
        reserva.setBounds(0, 33, 600, 83);
        contentPane.add(reserva);
        
        hotel = new JCheckBox("Book a hotel");
        hotel.addActionListener(this);
        hotel.setFont(new Font("Cascadia Code", Font.PLAIN, 13));
        hotel.setBackground(Color.WHITE);
        hotel.setBounds(371, 123, 180, 23);
        contentPane.add(hotel);
        
        hotelLbl = new JLabel();
        hotelLbl.setText("Room type");
        hotelLbl.setFont(new Font("Cascadia Code", Font.PLAIN, 13));
        hotelLbl.setBorder(null);
        hotelLbl.setBounds(381, 152, 150, 23);
        contentPane.add(hotelLbl);
        
        individual = new JRadioButton("Individual");
        individual.addActionListener(this);
        individual.setEnabled(false);
        individual.setFont(new Font("Cascadia Code", Font.PLAIN, 13));
        individual.setOpaque(false);
        habitacionTipo.add(individual);
        individual.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        individual.setBounds(391, 186, 109, 23);
        contentPane.add(individual);
        
        doble = new JRadioButton("Double");
        doble.addActionListener(this);
        doble.setEnabled(false);
        doble.setFont(new Font("Cascadia Code", Font.PLAIN, 13));
        doble.setOpaque(false);
        habitacionTipo.add(doble);
        doble.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        doble.setBounds(391, 220, 109, 23);
        contentPane.add(doble);
        
        multiple = new JRadioButton("Multiple");
        multiple.addActionListener(this);
        multiple.setEnabled(false);
        multiple.setFont(new Font("Cascadia Code", Font.PLAIN, 13));
        multiple.setOpaque(false);
        habitacionTipo.add(multiple);
        multiple.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        multiple.setBounds(391, 254, 109, 23);
        contentPane.add(multiple);
        
        numPersonas = new JTextField();
        numPersonas.setEnabled(false);
        numPersonas.setFont(new Font("Cascadia Code", Font.PLAIN, 13));
        numPersonas.setBorder(null);
        numPersonas.setBounds(401, 283, 150, 23);
        numPersonas.setToolTipText("Introduce el numero de personas");
        contentPane.add(numPersonas);
        
        JSeparator separatorNumPers = new JSeparator();
        separatorNumPers.setForeground(Color.BLACK);
        separatorNumPers.setBounds(401, 308, 150, 2);
        contentPane.add(separatorNumPers);
        
        accept = new JButton("Accept");
        accept.addActionListener(this);
        accept.addMouseListener(this);
        accept.addFocusListener(this);
        accept.setEnabled(false);
        accept.setBounds(335, 346, 93, 27);
        accept.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
        accept.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        accept.setFocusPainted(false);
        accept.setFont(new Font("Cascadia Code", Font.PLAIN, 13));
        accept.setContentAreaFilled(false);
        contentPane.add(accept);
        
        cancel = new JButton("Cancel");
        cancel.addActionListener(this);
        cancel.addMouseListener(this);
        cancel.addFocusListener(this);
        cancel.setBounds(438, 346, 93, 27);
        cancel.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
        cancel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        cancel.setFocusPainted(false);
        cancel.setFont(new Font("Cascadia Code", Font.PLAIN, 13));
        cancel.setContentAreaFilled(false);
        contentPane.add(cancel);
        
        setFocusTraversalPolicy(new FocusTraversalOnArray(new Component[]{hotel, individual, doble, multiple, numPersonas, accept, cancel, exit}));
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (hotel == e.getSource()) {
            individual.setEnabled(!individual.isEnabled());
            doble.setEnabled(!doble.isEnabled());
            multiple.setEnabled(!multiple.isEnabled());
            
            if (hotel.isSelected()) {
                accept.setEnabled(true);
            } else {
                accept.setEnabled(false);
            }

            if (!hotel.isSelected()) {
                habitacionTipo.clearSelection();
                numPersonas.setText("");
                numPersonas.setEnabled(false);

            }
        } else if (multiple == e.getSource()) {
            numPersonas.setEnabled(true);
        } else if (individual == e.getSource() || doble == e.getSource()) {
            numPersonas.setText("");
            numPersonas.setEnabled(false);
        } else if (accept == e.getSource()) {
            JOptionPane.showMessageDialog(null, "You pressed accept");
        } else if (cancel == e.getSource() || exit == e.getSource()) {
            this.dispose();
        }
    }

    
    @Override
    public void mouseClicked(MouseEvent e) {}

    @Override
    public void mousePressed(MouseEvent e) {
        if (panel == e.getSource()) {
            xMouse = e.getX();
            yMouse = e.getY();
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {}
    
    @Override
    public void mouseEntered(MouseEvent e) {
        if (accept == e.getSource()) {
            if (accept.isEnabled()) {
                accept.setOpaque(true);
                accept.setBackground(new Color(0, 64, 128));
                accept.setForeground(Color.WHITE);
            }
        } else if (cancel == e.getSource()) {
            cancel.setOpaque(true);
            cancel.setBackground(new Color(0, 64, 128));
            cancel.setForeground(Color.WHITE);
        } else if (exit == e.getSource()) {
            exit.setOpaque(true);
            exit.setBackground(Color.RED);
            exit.setForeground(Color.WHITE);
        }
    }

    @Override
    public void mouseExited(MouseEvent e) {
        if (accept == e.getSource()) {
            accept.setBackground(Color.WHITE);
            accept.setForeground(Color.BLACK);
        } else if (cancel == e.getSource()) {
            cancel.setBackground(Color.WHITE);
            cancel.setForeground(Color.BLACK);
        } else if (exit == e.getSource()) {
            exit.setBackground(Color.WHITE);
            exit.setForeground(Color.BLACK);
        }
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        if (panel == e.getSource()) {
            int x = e.getXOnScreen();
            int y = e.getYOnScreen();
            this.setLocation(x - xMouse, y - yMouse);
        }
    }

    @Override
    public void mouseMoved(MouseEvent e) {}

    @Override
    public void focusGained(FocusEvent e) {
        if (accept == e.getSource()) {
            accept.setOpaque(true);
            accept.setBackground(new Color(0, 64, 128));
            accept.setForeground(Color.WHITE);
        } else if (cancel == e.getSource()) {
            cancel.setOpaque(true);
            cancel.setBackground(new Color(0, 64, 128));
            cancel.setForeground(Color.WHITE);
        } else if (exit == e.getSource()) {
            exit.setOpaque(true);
            exit.setBackground(Color.RED);
            exit.setForeground(Color.WHITE);
        }
    }

    @Override
    public void focusLost(FocusEvent e) {
        if (accept == e.getSource()) {
            accept.setBackground(Color.WHITE);
            accept.setForeground(Color.BLACK);
        } else if (cancel == e.getSource()) {
            cancel.setBackground(Color.WHITE);
            cancel.setForeground(Color.BLACK);
        } else if (exit == e.getSource()) {
            exit.setBackground(Color.WHITE);
            exit.setForeground(Color.BLACK);
        }
    }
}
Java Swing 制表符排序

评论


答: 暂无答案