gpt4 book ai didi

java - 使用 Graphics2D 更新旋转的 JLabel 会导致新旧文本合并在一起

转载 作者:行者123 更新时间:2023-12-02 02:09:00 25 4
gpt4 key购买 nike

我试图将 JLabel 旋转 90 度,显示当前时间 90 度。经过一些研究后,大多数人推荐使用 Graphics2D 和 AffineTransform。这几乎可行,但是当更新时间中的分钟时,新数字似乎与旧数字合并。

/image/sn5Ej.jpg

这不会发生几秒钟。有人知道如何解决此问题或有替代解决方案吗?

驱动程序类别:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;

@SuppressWarnings("serial")
public class Driver extends JFrame implements KeyListener {

private boolean running = true;
ClockWidget clockWidget;
static Dimension screenSize;


public static void main(String[] args) {
screenSize = Toolkit.getDefaultToolkit().getScreenSize();
DisplayMode displayMode = new DisplayMode((int) screenSize.getWidth(), (int) screenSize.getHeight(), 32,
DisplayMode.REFRESH_RATE_UNKNOWN);
new Driver().run(displayMode);
}



public void run(DisplayMode displayMode) {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
getContentPane().setBackground(Color.BLACK);
setFont(new Font("Arial", Font.PLAIN, 24));

Screen screen = new Screen();
screen.setFullScreen(displayMode, this);

initClockWidgit();

addKeyListener(this);
System.out.println("RUNNING");
while (running) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
quitProgram(screen);
return;
}

public void initClockWidgit() {
clockWidget = new ClockWidget();
clockWidget.setFont(new Font("Arial", Font.PLAIN, 36));
clockWidget.setForeground(Color.WHITE);
clockWidget.setBackground(Color.BLUE);
clockWidget.setBounds((int) (screenSize.getWidth() * 0.90), (int) (screenSize.getHeight() * 0.10), 250, 100);

add(clockWidget);
new Thread(clockWidget).start();
}

public void quitProgram(Screen screen) {
screen.restoreScreen();
clockWidget.disable();
}

@Override
public void keyPressed(KeyEvent keyEvent) {
int keyCode = keyEvent.getKeyCode();
if (keyCode == KeyEvent.VK_SPACE) {
running = false;
}
keyEvent.consume();
}

@Override
public void keyReleased(KeyEvent keyEvent) {
keyEvent.consume();
}

@Override
public void keyTyped(KeyEvent keyEvent) {
keyEvent.consume();
}
}

ClockWidget 类:

import java.text.SimpleDateFormat;
import java.util.Calendar;

import javax.swing.JLabel;

public class ClockWidget extends RotatedJLabel implements Runnable{

private String currentTime;
private boolean running;

public ClockWidget() {
running = true;
}

@Override
public void run() {
while(running) {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("hh:mm:ss a");
currentTime = simpleDateFormat.format(calendar.getTime());
setText(currentTime);
}
}

public void disable() {
running = false;
}

}

RotatedJLabel 类:

[import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.AffineTransform;

import javax.swing.Icon;
import javax.swing.JLabel;

public class RotatedJLabel extends JLabel {

public RotatedJLabel() {
super();
}

public RotatedJLabel(Icon image) {
super(image);
}

public RotatedJLabel(Icon image, int horizontalAlignment) {
super(image, horizontalAlignment);
}

public RotatedJLabel(String text) {
super(text);
}

public RotatedJLabel(String text, Icon icon, int horizontalAlignment) {
super(text, icon, horizontalAlignment);
}

public RotatedJLabel(String text, int horizontalAlignment) {
super(text, horizontalAlignment);
}

@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
AffineTransform aT = g2.getTransform();
Shape oldshape = g2.getClip();
double x = getWidth()/2.0;
double y = getHeight()/2.0;
aT.rotate(Math.toRadians(90), x, y);
g2.setTransform(aT);
g2.setClip(oldshape);
super.paintComponent(g);
}
}

最佳答案

有几件事让我突然想到:

  • 我不会为此目的使用 JLabel,它是一个复杂的组件,从 JPanel 开始,简单地绘制文本会更简单。在我的测试中,当图形上下文旋转时,很难让大小调整提示正常工作。
  • 您没有管理组件的"new"大小调整提示,当与更复杂的布局结合使用时,这可能会成为一个问题,因为组件的宽度现在应该是高度,反之亦然
  • 我推荐key bindings API通过KeyListener
  • Swing 不是线程安全的,从 UI 上下文外部更新 UI 可能会产生许多问题;您应该使用 Swing Timer 而不是使用 Thread,并且由于您可能实际上只想更新秒数,因此以慢得多的速度运行它。请参阅Concurrency in SwingHow to Use Swing Timers了解更多详情
  • 并且 CalendarDate 已被有效弃用。请参阅Standard Calendar了解更多详情

例如...

Rotated text

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

public static void main(String[] args) {
new Test();
}

public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

private RotatedLabel timeLabel;
private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm:ss a");

public TestPane() {
setLayout(new GridBagLayout());
timeLabel = new RotatedLabel(currentTime());
add(timeLabel);

Timer timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
timeLabel.setText(currentTime());
}
});
timer.start();
}

public String currentTime() {
LocalTime lt = LocalTime.now();
return lt.format(formatter);
}

@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}

}

public class RotatedLabel extends JPanel {

private String text;

public RotatedLabel() {
super();
setOpaque(false);
setFont(UIManager.getDefaults().getFont("label.font"));
}

public RotatedLabel(String text) {
this();
this.text = text;
}

public String getText() {
return text;
}

public void setText(String text) {
this.text = text;
revalidate();
repaint();
}

protected Dimension getTextBounds() {
FontMetrics fm = getFontMetrics(getFont());
return new Dimension(fm.stringWidth(text), fm.getHeight());
}

@Override
public Dimension getPreferredSize() {
Dimension size = getTextBounds();
return new Dimension(size.height, size.width);
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
AffineTransform aT = g2.getTransform();
double x = getWidth() / 2.0;
double y = getHeight() / 2.0;
aT.rotate(Math.toRadians(90), x, y);
g2.setTransform(aT);

FontMetrics fm = g2.getFontMetrics();
float xPos = (getWidth() - fm.stringWidth(getText())) / 2.0f;
float yPos = ((getHeight() - fm.getHeight()) / 2.0f) + fm.getAscent();
g2.drawString(text, xPos, yPos);
g2.dispose();
}
}
}

现在,如果您“绝对、必须、不问任何问题”使用像 Label 这样的组件,那么我建议使用 JLayer相反。

不幸的是,我没有时间更新我的示例以使用 JLayer,但它们使用前身库 JXLayer

关于java - 使用 Graphics2D 更新旋转的 JLabel 会导致新旧文本合并在一起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50310352/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com