我需要在x-y轴坐标系中绘制google和yahoo访问时间。现在我绘制了x-y轴坐标系。
public void paintComponent(Graphics gl) {
Graphics2D g = (Graphics2D) gl;
g.setColor(new Color(222, 222, 222));
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(new Color(0, 0, 0));
int x=15;
int y=15;
g.drawString("20", 0, 10);
for(int i=1;i<=20;i++) {
g.drawLine(x, y+(35*(i-1)), x, y+(35*i));
g.drawString(""+(20-i), 0, y+(35*i));
}
for(int i=1;i<=10;i++) {
g.drawLine(x+(70*(i-1)),715, x+(70*i), 715);
g.drawString(""+i, x+(70*i),730);
}
}
现在我需要动态地在这个X-Y坐标系上重新绘制访问时间的值。但我知道何时调用repaint()。它将再次重绘()X-Y坐标.. 如何在不重新绘制X-Y坐标的情况下重新绘制访问时间值?
答案 0 :(得分:5)
将GUI显示的稳定背景部分放入BufferedImage,然后在paintComponent(...)
方法中绘制。
例如,
// Warning: code has not been run nor compiled and may contain errors.
public class MyGui extends JPanel {
public static final int BI_WIDTH = //..... ? the width of the image
public static final int BI_HEIGHT = // .....? the height of the image
private BufferedImage bImg;
public MyGui() {
bImg = makeImage();
// ... other code
}
public BufferedImage makeImage() {
BufferedImage bImg = new BufferedImage(BI_WIDTH, BI_HEIGHT,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = bImg.createGraphics();
// ... do your background drawing here, the display that doesn't change
g2.dispose();
return bImg;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (bImg != null) {
g.drawImage(bImg, 0, 0, this);
}
// ... draw the changing parts of your display
}
// note, if your image is going to fill up your JPanel, then it's
// also a good idea to override the getPreferredSize() method to make sure
// that the JPanel's size is correct and matches that of the image:
@Override
public Dimension getPreferredSize() {
return new Dimension(BI_WIDTH, BI_HEIGHT);
}
修改:注意有关getPreferredSize()
答案 1 :(得分:1)
如何在不重新绘制X-Y坐标的情况下重新绘制访问时间值?
如果再次重新绘制X / Y轴,为什么重要?如果您担心性能,它将不会产生任何明显的差异。
我知道这不是你提出的问题,但这里有一个解决方案,将X / Y轴描绘成单独的组件。然后,您可以独立绘制访问时间。它可能看起来有点复杂,但那是因为X / Y轴代码比你的更加绚丽。
此外,这可能会使绘画访问时间更容易,因为所有绘画偏移现在都是零,因为您在单独的面板上绘画。
import java.awt.*;
import javax.swing.*;
public class Axis extends JComponent
{
public static final int HORIZONTAL = 0;
public static final int VERTICAL = 1;
private int orientation;
private int ticks;
private int tickIncrement;
private int tickSize = 7;
public Axis(int orientation, int ticks, int tickIncrement)
{
this.orientation = orientation;
this.ticks = ticks;
this.tickIncrement = tickIncrement;
setFont( new Font("SansSerif", Font.PLAIN, 10) );
}
public Dimension getPreferredSize()
{
FontMetrics fontMetrics = getFontMetrics( getFont() );
int tickDimension = ticks * tickIncrement;
if (orientation == HORIZONTAL)
{
int height = (fontMetrics.getHeight() * 2) - fontMetrics.getAscent() + (tickSize * 2);
return new Dimension(tickDimension + getVerticalAxisWidth(), height);
}
else
{
int digits = String.valueOf(ticks).length();
int textWidth = fontMetrics.charWidth( '0' ) * digits;
int width = textWidth + (tickSize * 2) + 10;
return new Dimension(width, tickDimension);
}
}
protected void paintComponent(Graphics g)
{
// Paint background
g.setColor( getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
// Paint graph axis
g.setFont( getFont() );
g.setColor( getForeground() );
if (orientation == HORIZONTAL)
paintHorizontalAxis(g);
else
paintVerticalAxis(g);
}
private void paintHorizontalAxis(Graphics g)
{
FontMetrics fontMetrics = getFontMetrics( g.getFont() );
int label = 1;
int offset = tickIncrement;
int width = getWidth();
int adjustmentX = getVerticalAxisWidth() - 1;
int textOffset = tickSize + fontMetrics.getHeight();
while (offset <= width)
{
int hOffset = adjustmentX + offset;
g.drawLine(adjustmentX, 0, width, 0);
g.drawLine(hOffset, 0, hOffset, tickSize);
String text = "" + label;
int textAdjustment = (fontMetrics.stringWidth(text) - 1) / 2;
g.drawString(text, hOffset - textAdjustment, textOffset);
offset += tickIncrement;
label++;
}
}
private int getVerticalAxisWidth()
{
Container parent = (Container)getParent();
if (parent == null)
return 0;
LayoutManager manager = parent.getLayout();
if (manager instanceof BorderLayout)
{
BorderLayout layout = (BorderLayout)manager;
Component south = layout.getLayoutComponent(BorderLayout.SOUTH);
Component west = layout.getLayoutComponent(BorderLayout.WEST);
if (this.equals(south)
&& west instanceof Axis)
{
return west.getPreferredSize().width;
}
}
return 0;
}
private void paintVerticalAxis(Graphics g)
{
FontMetrics fontMetrics = getFontMetrics( g.getFont() );
int label = 1;
int offset = tickIncrement;
int x = getWidth() - 1;
int height = getHeight();
int textOffset = fontMetrics.getHeight() - fontMetrics.getAscent() + 1;
while (offset <= height)
{
int vOffset = height - offset;
g.drawLine(x, 0, x, height);
g.drawLine(x, vOffset, x - tickSize, vOffset);
String text = "" + label;
int textAdjustment = fontMetrics.stringWidth( text ) + tickSize + 5;
g.drawString(text, x - textAdjustment, vOffset + textOffset);
offset += tickIncrement;
label++;
}
}
private static void createAndShowUI()
{
JPanel graph = new JPanel( new BorderLayout() );
Axis vertical = new Axis(Axis.VERTICAL, 8, 50);
vertical.setBackground(Color.ORANGE);
graph.add(vertical, BorderLayout.WEST);
Axis horizontal = new Axis(Axis.HORIZONTAL, 12, 50);
horizontal.setBackground(Color.ORANGE);
graph.add(horizontal, BorderLayout.SOUTH);
// Do you custom painting on this panel
JPanel center = new JPanel();
center.setBackground( Color.YELLOW );
graph.add(center);
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(graph));
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
这仍然不是一个完美的解决方案,因为代码依赖于你使用BorderLayout来保存3个面板,但我不想编写自定义布局管理器来演示一个概念。