如何在 JLabel 中同时设置 setLocation 和 setText?
How to have simultaneous setLocation and setText in JLabel?
在我的代码的 try 块中,setText() 或 setLocation() 分别运行良好,如下所述:
以下代码根据给定的睡眠以正确的方式(每次 50 pxl)移动标签:
.........
label.setLocation((label.getLocationOnScreen().x+50),0);
Thread.sleep(time[i]);
...............
以下代码根据给定的睡眠正确设置文本("Name 1"、"Name 2" 等):
...................
label.setText(name[i]);
Thread.sleep(time[i]);
....................
以下代码根据给定的睡眠正确设置文本("Name 1"、"Name 2" 等)但不移动 JLabel:
....................
label.setText(name[i]);
label.setLocation((label.getLocationOnScreen().x+50),0);
Thread.sleep(time[i]);
....................
我两个都需要。换句话说,在第一乐章中它应该显示 "Name 1",在第二乐章中显示 "Name 2" 等等。
我是 java 和编程的新手。所以请帮助我获得所需的输出。感谢期待。
我的完整代码如下:
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
class Move {
JFrame frame = new JFrame();
JLabel label = new JLabel("Journey");
static int x=0;
public Move() {
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(800,600);
frame.setLayout(new GridLayout());
frame.add(label);
label.setLocation(0, 0);
frame.setVisible(true);
doAll();
}
void doAll(){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try{
String[] name={"Name 1","Name 2","Name 3","Name 4","Name 5","Name 6","Name 7","Name 8","Name 9","Name 10"};
int time []={2000,1000,2000,1000,2000,1000,2000,1000,2000,1000};
for (int i=0; i<10; i++){
label.setText(name[i]);
label.setLocation((label.getLocationOnScreen().x+50),0);
Thread.sleep(time[i]);
}
}catch(Exception ae){
}
}
});
t.start();
}
public static void main(String[]args){
new Move();
}
}
问题看起来是框架的 LayoutManager 正在为您设置标签的位置。
您需要做的是将布局设置为空:
frame.setLayout(null);
这将使框架不会尝试自行布局组件。
那么你可以
label.setLocation((label.getLocationOnScreen().x+50),0);
但是,没有布局并不理想,而且 GridLayout
也不是您想要的真正好东西。
原因:GridLayout
将始终按照您编写“container.add(component)
”语句的顺序对组件进行排序。您不能将组件放在特定位置,除非为之前的所有位置插入虚拟组件。
您可能想尝试 GridBagLayout
.. 在 GridBagLayout
中,您只需在关键事件上更新动态面板的位置,它就会显示在顶部该位置的固定面板。
您可以在 JPanel 上绘制图像并移动图像,而不是尝试移动 Swing 组件。
这是我创建的 GUI。
您必须通过调用 SwingUtilities invokeLater 方法来启动 Swing 应用程序。该方法将所有Swing组件的创建和使用放在Event Dispatch thread (EDT).
每当您尝试协调 2 个或更多阵列时,您应该考虑创建一个模型 class。我创建了 Leg class 来保存名称和延迟。这样,我只需要在旅程 class.
中创建一个列表
我从 JPanel 创建了一个 DrawingPanel。始终在 JPanel 上创建 GUI。切勿直接在 JFrame 上创建 GUI。
运行 您的动画在单独的 运行nable、Thread 或 Swing Timer 中。 GUI 运行 在它自己的线程上,你的动画代码必须在不同的线程中 运行,否则你会阻止 GUI 更新。
由于动画 运行 在单独的线程中进行,因此绘图面板中 Leg 的设置包含在 SwingUtilities invokeLater 方法中。这确保绘图发生在事件调度线程 (EDT) 上。
创建JFrame时,我在JFrame中添加了一个WindowListener。这样我就可以检测到 window 关闭,并在退出程序之前停止动画。
这是代码。
package com.ggl.testing;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ImageMove implements Runnable {
private JFrame frame;
private JourneyRunnable journeyRunnable;
public static void main(String[] args) {
SwingUtilities.invokeLater(new ImageMove());
}
@Override
public void run() {
frame = new JFrame("Image Move");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent event) {
exitProcedure();
}
});
DrawingPanel drawingPanel = new DrawingPanel();
frame.add(drawingPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
journeyRunnable = new JourneyRunnable(drawingPanel, new Journey());
new Thread(journeyRunnable).start();
}
public void exitProcedure() {
journeyRunnable.setRunning(false);
frame.dispose();
System.exit(0);
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = -8498462824787395933L;
private int xPos, yPos, width, height;
private Leg leg;
public DrawingPanel() {
this.width = 100;
this.height = 50;
this.xPos = 0;
this.yPos = (200 - height) / 2;
this.setPreferredSize(new Dimension(800, 200));
}
public void setLeg(Leg leg) {
this.leg = leg;
this.xPos += 10;
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.ORANGE);
g.fillRect(xPos, yPos, width, height);
if (leg != null) {
g.setColor(Color.BLACK);
centerString(g, new Rectangle(xPos, yPos, width, height),
leg.getName(), g.getFont());
}
}
/**
* This method centers a <code>String</code> in a bounding
* <code>Rectangle</code>.
*
* @param g
* - The <code>Graphics</code> instance.
* @param r
* - The bounding <code>Rectangle</code>.
* @param s
* - The <code>String</code> to center in the bounding
* rectangle.
* @param font
* - The display font of the <code>String</code>
*
* @see java.awt.Graphics
* @see java.awt.Rectangle
* @see java.lang.String
*/
public void centerString(Graphics g, Rectangle r, String s, Font font) {
FontRenderContext frc = new FontRenderContext(null, true, true);
Rectangle2D r2D = font.getStringBounds(s, frc);
int rWidth = (int) Math.round(r2D.getWidth());
int rHeight = (int) Math.round(r2D.getHeight());
int rX = (int) Math.round(r2D.getX());
int rY = (int) Math.round(r2D.getY());
int a = (r.width / 2) - (rWidth / 2) - rX;
int b = (r.height / 2) - (rHeight / 2) - rY;
g.setFont(font);
g.drawString(s, r.x + a, r.y + b);
}
}
public class JourneyRunnable implements Runnable {
private boolean running;
private DrawingPanel drawingPanel;
private Journey journey;
public JourneyRunnable(DrawingPanel drawingPanel, Journey journey) {
this.drawingPanel = drawingPanel;
this.journey = journey;
this.running = true;
}
@Override
public void run() {
while (running) {
Leg leg = journey.getLeg();
setLeg(leg);
sleep(leg);
}
}
public void setLeg(final Leg leg) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
drawingPanel.setLeg(leg);
}
});
}
private void sleep(Leg leg) {
try {
Thread.sleep(leg.getDelay());
} catch (InterruptedException e) {
}
}
public void setRunning(boolean running) {
this.running = running;
}
}
public class Journey {
private int index;
private List<Leg> legs;
public Journey() {
this.legs = new ArrayList<>();
this.legs.add(new Leg("Name 1", 2000L));
this.legs.add(new Leg("Name 2", 1000L));
this.legs.add(new Leg("Name 3", 2000L));
this.legs.add(new Leg("Name 4", 1000L));
this.legs.add(new Leg("Name 5", 2000L));
this.legs.add(new Leg("Name 6", 1000L));
this.legs.add(new Leg("Name 7", 2000L));
this.legs.add(new Leg("Name 8", 1000L));
this.legs.add(new Leg("Name 9", 2000L));
this.legs.add(new Leg("Name 10", 1000L));
this.index = 0;
}
public Leg getLeg() {
Leg leg = legs.get(index);
index = ++index % legs.size();
return leg;
}
}
public class Leg {
private final String name;
private final long delay;
public Leg(String name, long delay) {
this.name = name;
this.delay = delay;
}
public String getName() {
return name;
}
public long getDelay() {
return delay;
}
}
}
在我的代码的 try 块中,setText() 或 setLocation() 分别运行良好,如下所述:
以下代码根据给定的睡眠以正确的方式(每次 50 pxl)移动标签:
.........
label.setLocation((label.getLocationOnScreen().x+50),0);
Thread.sleep(time[i]);
...............
以下代码根据给定的睡眠正确设置文本("Name 1"、"Name 2" 等):
...................
label.setText(name[i]);
Thread.sleep(time[i]);
....................
以下代码根据给定的睡眠正确设置文本("Name 1"、"Name 2" 等)但不移动 JLabel:
....................
label.setText(name[i]);
label.setLocation((label.getLocationOnScreen().x+50),0);
Thread.sleep(time[i]);
....................
我两个都需要。换句话说,在第一乐章中它应该显示 "Name 1",在第二乐章中显示 "Name 2" 等等。
我是 java 和编程的新手。所以请帮助我获得所需的输出。感谢期待。
我的完整代码如下:
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
class Move {
JFrame frame = new JFrame();
JLabel label = new JLabel("Journey");
static int x=0;
public Move() {
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(800,600);
frame.setLayout(new GridLayout());
frame.add(label);
label.setLocation(0, 0);
frame.setVisible(true);
doAll();
}
void doAll(){
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try{
String[] name={"Name 1","Name 2","Name 3","Name 4","Name 5","Name 6","Name 7","Name 8","Name 9","Name 10"};
int time []={2000,1000,2000,1000,2000,1000,2000,1000,2000,1000};
for (int i=0; i<10; i++){
label.setText(name[i]);
label.setLocation((label.getLocationOnScreen().x+50),0);
Thread.sleep(time[i]);
}
}catch(Exception ae){
}
}
});
t.start();
}
public static void main(String[]args){
new Move();
}
}
问题看起来是框架的 LayoutManager 正在为您设置标签的位置。
您需要做的是将布局设置为空:
frame.setLayout(null);
这将使框架不会尝试自行布局组件。
那么你可以
label.setLocation((label.getLocationOnScreen().x+50),0);
但是,没有布局并不理想,而且 GridLayout
也不是您想要的真正好东西。
原因:GridLayout
将始终按照您编写“container.add(component)
”语句的顺序对组件进行排序。您不能将组件放在特定位置,除非为之前的所有位置插入虚拟组件。
您可能想尝试 GridBagLayout
.. 在 GridBagLayout
中,您只需在关键事件上更新动态面板的位置,它就会显示在顶部该位置的固定面板。
您可以在 JPanel 上绘制图像并移动图像,而不是尝试移动 Swing 组件。
这是我创建的 GUI。
您必须通过调用 SwingUtilities invokeLater 方法来启动 Swing 应用程序。该方法将所有Swing组件的创建和使用放在Event Dispatch thread (EDT).
每当您尝试协调 2 个或更多阵列时,您应该考虑创建一个模型 class。我创建了 Leg class 来保存名称和延迟。这样,我只需要在旅程 class.
中创建一个列表
我从 JPanel 创建了一个 DrawingPanel。始终在 JPanel 上创建 GUI。切勿直接在 JFrame 上创建 GUI。
运行 您的动画在单独的 运行nable、Thread 或 Swing Timer 中。 GUI 运行 在它自己的线程上,你的动画代码必须在不同的线程中 运行,否则你会阻止 GUI 更新。
由于动画 运行 在单独的线程中进行,因此绘图面板中 Leg 的设置包含在 SwingUtilities invokeLater 方法中。这确保绘图发生在事件调度线程 (EDT) 上。
创建JFrame时,我在JFrame中添加了一个WindowListener。这样我就可以检测到 window 关闭,并在退出程序之前停止动画。
这是代码。
package com.ggl.testing;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ImageMove implements Runnable {
private JFrame frame;
private JourneyRunnable journeyRunnable;
public static void main(String[] args) {
SwingUtilities.invokeLater(new ImageMove());
}
@Override
public void run() {
frame = new JFrame("Image Move");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent event) {
exitProcedure();
}
});
DrawingPanel drawingPanel = new DrawingPanel();
frame.add(drawingPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
journeyRunnable = new JourneyRunnable(drawingPanel, new Journey());
new Thread(journeyRunnable).start();
}
public void exitProcedure() {
journeyRunnable.setRunning(false);
frame.dispose();
System.exit(0);
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = -8498462824787395933L;
private int xPos, yPos, width, height;
private Leg leg;
public DrawingPanel() {
this.width = 100;
this.height = 50;
this.xPos = 0;
this.yPos = (200 - height) / 2;
this.setPreferredSize(new Dimension(800, 200));
}
public void setLeg(Leg leg) {
this.leg = leg;
this.xPos += 10;
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.ORANGE);
g.fillRect(xPos, yPos, width, height);
if (leg != null) {
g.setColor(Color.BLACK);
centerString(g, new Rectangle(xPos, yPos, width, height),
leg.getName(), g.getFont());
}
}
/**
* This method centers a <code>String</code> in a bounding
* <code>Rectangle</code>.
*
* @param g
* - The <code>Graphics</code> instance.
* @param r
* - The bounding <code>Rectangle</code>.
* @param s
* - The <code>String</code> to center in the bounding
* rectangle.
* @param font
* - The display font of the <code>String</code>
*
* @see java.awt.Graphics
* @see java.awt.Rectangle
* @see java.lang.String
*/
public void centerString(Graphics g, Rectangle r, String s, Font font) {
FontRenderContext frc = new FontRenderContext(null, true, true);
Rectangle2D r2D = font.getStringBounds(s, frc);
int rWidth = (int) Math.round(r2D.getWidth());
int rHeight = (int) Math.round(r2D.getHeight());
int rX = (int) Math.round(r2D.getX());
int rY = (int) Math.round(r2D.getY());
int a = (r.width / 2) - (rWidth / 2) - rX;
int b = (r.height / 2) - (rHeight / 2) - rY;
g.setFont(font);
g.drawString(s, r.x + a, r.y + b);
}
}
public class JourneyRunnable implements Runnable {
private boolean running;
private DrawingPanel drawingPanel;
private Journey journey;
public JourneyRunnable(DrawingPanel drawingPanel, Journey journey) {
this.drawingPanel = drawingPanel;
this.journey = journey;
this.running = true;
}
@Override
public void run() {
while (running) {
Leg leg = journey.getLeg();
setLeg(leg);
sleep(leg);
}
}
public void setLeg(final Leg leg) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
drawingPanel.setLeg(leg);
}
});
}
private void sleep(Leg leg) {
try {
Thread.sleep(leg.getDelay());
} catch (InterruptedException e) {
}
}
public void setRunning(boolean running) {
this.running = running;
}
}
public class Journey {
private int index;
private List<Leg> legs;
public Journey() {
this.legs = new ArrayList<>();
this.legs.add(new Leg("Name 1", 2000L));
this.legs.add(new Leg("Name 2", 1000L));
this.legs.add(new Leg("Name 3", 2000L));
this.legs.add(new Leg("Name 4", 1000L));
this.legs.add(new Leg("Name 5", 2000L));
this.legs.add(new Leg("Name 6", 1000L));
this.legs.add(new Leg("Name 7", 2000L));
this.legs.add(new Leg("Name 8", 1000L));
this.legs.add(new Leg("Name 9", 2000L));
this.legs.add(new Leg("Name 10", 1000L));
this.index = 0;
}
public Leg getLeg() {
Leg leg = legs.get(index);
index = ++index % legs.size();
return leg;
}
}
public class Leg {
private final String name;
private final long delay;
public Leg(String name, long delay) {
this.name = name;
this.delay = delay;
}
public String getName() {
return name;
}
public long getDelay() {
return delay;
}
}
}