2015-04-28 44 views
4

主要问题是我想用一些标签绘制图形。对于绘图,我使用以下类:使用Swing绘图文本

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); 

Label on the right side

代码的位置使得在行为没有区别。如果我注释掉所有的代码,但是标签或者我把标签绘制放在函数的顶部,它没有任何区别。

那么,我怎么能让这个标签在我第一次打电话重绘时渲染?

编辑:这里是这使得窗口中的代码:

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); 
    } 

} 

和代码在画布构造器:

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); 
} 

画布和其他一些成分是单身,但我想这不应该是一个问题,因为只有一个窗口存在一个画布上。

+1

告诉你如何把'Canvas'在父容器。 – alex2410

+1

使用'FontMetrics'确定文本的长度和高度 – MadProgrammer

+1

您是否有任何可以使[_Graphics上下文在第一个paint_上未对齐](http://stackoverflow.com/q/23507422/261156)? –

回答

0

这是很难知道没有一个完全可运行的例子,但是,你不应该对文本的大小来做出假设,而是应该使用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()); 

Working with Text APIs细看更多细节。

另一个问题可能是,如果您以前翻译Graphics语境,不必先复制或逆转翻译

+1

@mKorbel因为没有足够的空间发表评论... – MadProgrammer