【问题标题】:Right aligned cursor not showing through in a JTextPane component右对齐光标未在 JTextPane 组件中显示
【发布时间】:2013-01-15 15:19:00
【问题描述】:

我有一个 JTextPane 夹在 2 个 JLabels 之间 - 如果我将光标放在文本窗格的最左侧但不在右侧,是否有已知原因导致光标显示?

这是更好地说明我的意思的代码:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;

public class Testing {
    /**
     * @param args
     */
    public static void main(String[] args) {
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel cp = new JPanel(new BorderLayout());
        f.setContentPane(cp);

        final SubPanel subPanel = new SubPanel();

        cp.add(subPanel, BorderLayout.CENTER);

        JPanel buttonPanel = new JPanel(new FlowLayout());
        buttonPanel.add(new JLabel("Align"));
        final JComboBox alignCB = new JComboBox(new String[] {"left", "centre", "right"});
        alignCB.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                subPanel.align((String) alignCB.getSelectedItem());
            }
        });
        buttonPanel.add(alignCB);
        buttonPanel.add(new JLabel("Justify"));
        final JComboBox justifyCB = new JComboBox(new String[] {"left", "centre", "right"});
        justifyCB.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                subPanel.justify((String) justifyCB.getSelectedItem());
            }
        });
        buttonPanel.add(justifyCB);

        JTextField tf = new JTextField("TF");
        tf.setBorder(null);
        buttonPanel.add(tf);

        cp.add(buttonPanel, BorderLayout.NORTH);

        f.pack();
        f.setSize(new Dimension(300,300));
        f.setLocation(300, 300);
        f.setVisible(true);

    }

    public static class SubPanel extends JPanel {
        JPanel innerPanel = new JPanel(new GridBagLayout());
        TextPaneWidget[] tps = new TextPaneWidget[3];

        public SubPanel() {
            //                setBorder(BorderFactory.createLineBorder(Color.RED));
            setBorder(null);
            //                innerPanel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
            innerPanel.setBorder(null);

            for (int i = 0; i < tps.length; i++) {
                tps[i] = new TextPaneWidget();
            }

            int gridy = 0;
            for (TextPaneWidget tp : tps) {
                innerPanel.add(tp, new GridBagConstraints(0,gridy, 1,1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0), 0, 0));
                gridy++;
            }

            setLayout(new GridBagLayout());

            add(innerPanel, new GridBagConstraints(0,0, 1,1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
        }

        public void align(String alignment) {
            System.out.println("Align: " + alignment);

            int anchor = GridBagConstraints.CENTER;
            if ("right".equals(alignment)) {
                anchor = GridBagConstraints.EAST;
            } else if ("left".equals(alignment)) {
                anchor = GridBagConstraints.WEST;
            }

            GridBagLayout gbl = (GridBagLayout) getLayout();
            gbl.setConstraints(innerPanel, new GridBagConstraints(0,0, 1,1, 1.0, 0.0, anchor, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));

            revalidate();
            repaint();
        }

        public void justify(String justification) {
            System.out.println("Justify: " + justification);

            for (TextPaneWidget tp : tps) {
                tp.justify(justification);
            }
        }
    }

    public static class MyDocument extends DefaultStyledDocument {
        @Override
        public void insertString(int offset, String text, AttributeSet attributeSet) throws BadLocationException {
            SimpleAttributeSet attrs = new SimpleAttributeSet(attributeSet);
            StyleConstants.setForeground(attrs, Color.WHITE);
            StyleConstants.setBackground(attrs, Color.RED);
            super.insertString(offset, text, attrs);
        }
    }

    public static class TextPaneWidget extends JPanel {
        JTextPane tp = new JTextPane();
        JLabel lSpace = new JLabel("   ");
        JLabel rSpace = new JLabel("   ");

        public TextPaneWidget() {
            //                setBorder(BorderFactory.createLineBorder(Color.GREEN));
            setBorder(null);

            Font font = new Font("monospaced", Font.BOLD, 13);
            tp.setBorder(null);
            tp.setDocument(new MyDocument());
            tp.setFont(font);
            tp.setText("Text");
            tp.setOpaque(true);

            setLayout(new GridBagLayout());

            lSpace.setBackground(Color.MAGENTA);
            lSpace.setOpaque(true);
            lSpace.setBorder(null);
            add(lSpace, new GridBagConstraints(0,0, 1,1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.VERTICAL, new Insets(0,0,0,0), 0, 0));

            add(tp, new GridBagConstraints(1,0, 1,1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));

            rSpace.setBackground(Color.MAGENTA);
            rSpace.setOpaque(true);
            rSpace.setBorder(null);
            add(rSpace, new GridBagConstraints(2,0, 1,1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.VERTICAL, new Insets(0,0,0,0), 0, 0));

            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    tp.setCaretPosition((e.getX() < tp.getX()) ? 0 : tp.getText().length());
                    tp.requestFocusInWindow();
                }
            });

            lSpace.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    tp.setCaretPosition(0);
                    tp.requestFocusInWindow();
                }
            });

            rSpace.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    tp.setCaretPosition(tp.getText().length());
                    tp.requestFocusInWindow();
                }
            });

        }

        public void justify(String justification) {
            double leftWeight = 0.5;
            double rightWeight = 0.5;
            if ("right".equals(justification)) {
                leftWeight = 1.0;
                rightWeight = 0.0;
            } else if ("left".equals(justification)) {
                leftWeight = 0.0;
                rightWeight = 1.0;
            }

            GridBagLayout gbl = (GridBagLayout) getLayout();
            gbl.setConstraints(lSpace, new GridBagConstraints(0,0, 1,1, leftWeight, 0.0, GridBagConstraints.EAST, GridBagConstraints.VERTICAL, new Insets(0,0,0,0), 0, 0));
            gbl.setConstraints(rSpace, new GridBagConstraints(2,0, 1,1, rightWeight, 0.0, GridBagConstraints.WEST, GridBagConstraints.VERTICAL, new Insets(0,0,0,0), 0, 0));
            revalidate();
            repaint();
        }
    }
}

【问题讨论】:

  • 我在装有 Java 6 的 Windows XP 计算机上看不到它。无论对齐方式或对齐方式如何,光标在 JTextPane 上都可以正常显示。现在,我必须左键单击希望光标所在的 JTextPane 以使 JTextPane 获得焦点。使用从左到右的字符方向时,不能将光标放在最右边的字符上。
  • 如果我删除了文本字段上的 setBorder(null),它可以正常工作,但会在其周围放置一个可怕的白色边框。我尝试将其更改为 tp.setBorder(BorderFactory.createEmptyBorder(0,0,0,1));但同样,我得到一个轻微的白色间隙 - 有没有办法设置空边框间隙颜色??
  • 我不明白你想要什么效果。 tp.setBorder(null) 等同于 tp.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
  • 我正在使用 Windows 7,所以不确定它是否不同,但基本上光标从文本框的右侧消失(不会发生在左侧)。如果我使用 tp.setBorder(BorderFactory.createEmptyBorder(0,0,0,1)); (注意右边框的 1 )它添加了一个小的白色边框,如果我单击文本框的最右边的点,则会出现光标 - 我的问题是为什么在创建空边框时这有效,但不适用于任何其他边框类型...??
  • 啊,我终于明白你在问什么了。我猜在 JTextPane 中没有地方可以绘制最右边的光标,除非您在右侧提供一个像素空间。如果你想要一个一个像素的右线边框,你将不得不编写你自己的实现边框的类。标准的 BorderFactory 方法都不会这样做。

标签: java swing cursor textfield


【解决方案1】:

我想我明白发生了什么。感谢提供代码。

定义 JTextPane 时,默认边框是 3 像素的空边框。当光标位于最右侧位置时,此空边框为文本窗格光标提供了一个显示位置。光标位于最右边,可以在一行字符的末尾输入字符。

当您定义一个空边框时,它与一个 0 像素的空边框相同,当文本窗格光标位于最右边的位置时,它没有地方可以绘制。

为了在最右边看到光标,您必须定义一个至少有 1 个右像素的空边框。如果您希望它更具视觉吸引力,请添加 1 个左侧像素。

tp.setBorder(BorderFactory.createEmptyBorder(0,1,0,1));

您必须定义一个空边框,因为空边框是唯一不绘制的Border。绘制的Border 将绘制在最右边的文本窗格光标上。

因此,JTextPane 需要使用具有至少一个右侧像素的空边框来显示最右侧的光标。

编辑添加:

当您使用GridBagLayout 时,这样的方法可以减少您在添加组件时必须处理的参数数量。

protected void addComponent(Container container, Component component,
        int gridx, int gridy, int gridwidth, int gridheight, 
        Insets insets, int anchor, int fill) {
    GridBagConstraints gbc = new GridBagConstraints(gridx, gridy,
            gridwidth, gridheight, 1.0D, 1.0D, anchor, fill, insets, 0, 0);
    container.add(component, gbc);
}

【讨论】:

    【解决方案2】:

    将背景设置为以下可解决此问题...

    tp.setBackground(Color.RED);
    tp.setOpaque(true);
    

    【讨论】:

      猜你喜欢
      • 2015-12-04
      • 2016-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-10
      • 1970-01-01
      • 2013-11-03
      相关资源
      最近更新 更多