如何在不重新绘制 XY 坐标的情况下重新绘制访问时间的值?
重新绘制 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 个面板,但我不想编写自定义布局管理器来演示概念。