使用Swing绘制文本

5
主要问题是我想用几个标签绘制一个图表。我使用以下类进行绘制:
public class Canvas extends JPanel {

    // Lot of other methods

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;

        // Other code

        g2.setColor(Style.LIGHT_GREY);
        g2.fillOval(node.getPosition().x, node.getPosition().y, Style.SHAPE_SIZE, Style.SHAPE_SIZE);

        g2.setColor(Style.DARK_GREY);
        g2.setStroke(new BasicStroke(1.5f));
        g2.drawOval(node.getPosition().x, node.getPosition().y, Style.SHAPE_SIZE, Style.SHAPE_SIZE);

        //Draw token
        g2.setColor(Style.DARK_GREY);
        g2.setFont(new Font("Monospaced", Font.PLAIN, 12));
        String token = ((Place)node).getTokens().toString();
        g2.drawString(token, 
                (int) (node.getNodeCenterPosition().x - 3.5*token.length()), node.getNodeCenterPosition().y + CHAR_HEIGHT);

        //Draw label
        g2.drawString("P1", node.getPosition().x-8, node.getPosition().y-8);

        // More code
    }

}

不用关心坐标,它们都已经设置正确。奇怪的行为从这里的最后一个drawString开始:

//Draw label
g2.drawString("P1", node.getPosition().x-8, node.getPosition().y-8);

一旦调用paintComponent,之前的所有代码都会被渲染,但是这段代码不会。但是如果我再次触发paintComponent(通过外部调用canvas.repaint()),它就会显示出来。
下面是第一次重绘后画布的状态:

No label

下面是第二次重绘后画布的状态:

With label

附加说明: 如果我把标签放在圆盘的右边,它在第一次重绘时就正常渲染出来了。
g2.drawString("P1", node.getPosition().x+50, node.getPosition().y+30);

标签在右侧

代码的位置不会影响行为。如果我注释掉除标签外的所有代码,或者将标签的绘制放在函数的顶部,都不会产生任何影响。

那么,我该如何使这个标签在第一次调用repaint时呈现出来?

编辑:以下是渲染窗口的代码:

public class MainWindow extends JFrame {

    private MainWindow() {
        super();

        setVisible(true);
        setResizable(false);
        setSize(1280, 750);

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        this.setJMenuBar(MainMenu.getInstance());       
        add(Canvas.getInstance(), BorderLayout.CENTER);     
        add(ToolBar.getInstance(), BorderLayout.PAGE_START);        
        add(LeftPanel.getInstance(), BorderLayout.LINE_START);
    }

}

Canvas构造函数中的代码:

private Canvas() {
    super();
    this.setFocusable(true);
    this.setBackground(Style.BACKGROUND);

    this.popupNewNode = new JPopupMenu();
    this.popupNewNode.setFocusable(false);

    this.newPlace = new JMenuItem("New Place");
    this.newTransition = new JMenuItem("New Transition");

    this.popupNewNode.add(newPlace);
    this.popupNewNode.add(newTransition);
}
< p > 画布和其他一些组件是单例的,但我想这不应该成为问题,因为只有一个窗口存在,且上面只有一个画布。 < /p >

1
展示如何将 Canvas 放置在父容器上。 - alex2410
1
使用 FontMetrics 来确定文本的长度和高度。 - MadProgrammer
1
你有什么东西可以解决Graphics Context misaligned on first paint的问题吗? - Catalina Island
2
setVisible(true); 必须是最后一行代码 == 你的主要问题 - mKorbel
1
为了更快地获得帮助,请发布一个MCVE(Minimal Complete Verifiable Example,最小完整可验证示例)或SSCCE(Short,Self Contained,Correct Example,简短,自包含,正确的示例)。 - Andrew Thompson
显示剩余4条评论
1个回答

1

如果没有完整可运行的示例,很难知道具体情况,但是,您不应该对文本大小进行假设,而应该使用FontMetrics

FontMetrics fm = g.getFontMetrics();
int width = fm.stringWidth("P1");
int height = fm.getHeight();
g.drawString("P1", node.getPosition().x - width, (node.getPosition().y - height) + fm.getAscent());

请仔细查看使用文本API以获取更多详细信息。
另一个问题可能是,如果您之前翻译了Graphics上下文而没有先复制它或反转翻译。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接