这是一个困扰我几个小时的问题,我
自己无法找到解决方案……
我在网上发现了类似的话题,但是我找不到
很好的解释并且尽可能简单的解决方案的完全相同的问题。我也
看过EDT和SwingWorker API文档,但对
我来说太复杂了:(
所以,让我们说清楚。我有一个带有JLabel的简单JFrame,其中
包含我的图像:
private static class MyJLabel extends JLabel {
private ImageIcon img = null;
public MyJLabel(ImageIcon img) {
super();
this.img = img;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img.getImage(), 0, 0, getWidth(), getHeight(), this);
}
}
private static class MyJFrame extends JFrame implements Runnable {
private BufferedImage img = null;
private MyJLabel label = null;
public MyJFrame(BufferedImage image, String title) {
super(title);
img = image;
}
@Override
public void run() {
Dimension dims = new Dimension(img.getWidth(), img.getHeight());
dims = new Dimension(dims.width / 2, dims.height / 2);
label = new MyJLabel(new ImageIcon(img));
label.setPreferredSize(dims);
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
label.repaint();
}
});
setLayout(new BorderLayout());
getContentPane().add(BorderLayout.CENTER, label);
setLocation(200, 200);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
pack();
setVisible(true);
}
public void changeImage(BufferedImage image) {
img = image;
if (label != null) {
label.setIcon(new ImageIcon(img));
label.repaint();
}
}
}
It’s invoked by this piece of code:
buffer = receiveImage(in); // download image
MyJFrame f = null;
javax.swing.SwingUtilities.invokeLater(f = new MyJFrame(buffer, "RDP"));
int x = 0;
while (x <= 15) {
txt.println("next"); // notify server that we are ready
while (true) { // wait for server
if (reader.readLine().equals("ready")) break;
}
buffer = receiveImage(in); // download image
// do some magic here and refresh image somehow :(
f.changeImage(buffer); // does not work!
x++;
}
不幸的是,我使用changeImage方法的方法不起作用-什么也没
发生(GUI启动但从未更新)。
我对此将无济于事。带有适当 解释的简单,有效的示例
将是最受赞赏的;)
问候!
就个人而言,我可以在将其应用于标签之前调整其大小,或者使用aJPanel进行绘画。JLabel必须拖延很多功能。
举例来说,您遇到的问题是您实际上是在使用 该图像setIcon来设置图像,但是却 在其顶部paintComponent绘制了另一个(初始)图像
您的自定义标签将aImageIcon作为初始参数并将其绘制为初始参数
private static class MyJLabel extends JLabel {
private ImageIcon img = null;
public MyJLabel(ImageIcon img) {
super();
this.img = img;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img.getImage(), 0, 0, getWidth(), getHeight(), this);
}
}
You initialise it as such…
label = new MyJLabel(new ImageIcon(img));
It should be noted that if you used the Icon
support of JLabel
, this…
label.setPreferredSize(dims);
会无关紧要,因为JLabel会使用图标的大小来确定其
首选的大小……但无论如何……
然后,使用此按钮更新图标。
img = image;
if (label != null) {
label.setIcon(new ImageIcon(img));
label.repaint();
}
应该指出的是,根据您的示例,这实际上是在EDT之外调用的,这很危险,并可能导致油漆变脏。
但setIcon永远不会改变的价值img范围内MyLabel,所以当你的paintComponent
方法被调用时,你实际上是画了你的图标
已经在更新提供…
// Paint the new Icon
super.paintComponent(g);
// Paint the old/initial image...
g.drawImage(img.getImage(), 0, 0, getWidth(), getHeight(), this);
Updated
就个人而言,我要做的是使用a之类的东西创建一个自定义组件,JPanel并根据
面板的当前大小缩放原始图像,例如……
现在,通常情况下,在执行图像缩放时,我更喜欢使用Java中演示的分治方法:维护JPanel
背景图像的宽高比,但是在此示例中,我只是AffineTransform为了简单起见使用
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ScalableImageExample {
public static void main(String[] args) {
new ScalableImageExample();
}
public ScalableImageExample() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
try {
ResizableImagePane pane = new ResizableImagePane();
pane.setImage(...);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException exp) {
exp.printStackTrace();
}
}
});
}
public class ResizableImagePane extends JPanel {
private Image img;
public ResizableImagePane() {
}
public void setImage(Image value) {
if (img != value) {
Image old = img;
this.img = value;
firePropertyChange("image", old, img);
revalidate();
repaint();
}
}
public Image getImage() {
return img;
}
@Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(this), img.getHeight(this));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Graphics2D g2d = (Graphics2D) g.create();
int width = getWidth();
int height = getHeight();
double scaleFactor = getScaleFactorToFit(new Dimension(img.getWidth(this), img.getHeight(this)), getSize());
int x = (int)((width - (img.getWidth(this) * scaleFactor)) / 2);
int y = (int)((height - (img.getHeight(this) * scaleFactor)) / 2);
AffineTransform at = new AffineTransform();
at.translate(x, y);
at.scale(scaleFactor, scaleFactor);
g2d.setTransform(at);
g2d.drawImage(img, 0, 0, this);
g2d.dispose();
}
}
public double getScaleFactor(int iMasterSize, int iTargetSize) {
return (double) iTargetSize / (double) iMasterSize;
}
public double getScaleFactorToFit(Dimension original, Dimension toFit) {
double dScale = 1d;
if (original != null && toFit != null) {
double dScaleWidth = getScaleFactor(original.width, toFit.width);
double dScaleHeight = getScaleFactor(original.height, toFit.height);
dScale = Math.min(dScaleHeight, dScaleWidth);
}
return dScale;
}
}
}
问题内容: 我有一个JList,它显示来自矢量的信息。然后,用户可以从该向量中添加和删除信息。从Vector添加/删除项目时,是否可以刷新JFrame中的JList?目前我正在做.. 但这不会将JList刷新为新内容。我检查了一下,矢量内容等确实发生了变化,但列表没有刷新。为什么?我该如何解决? 问题答案: 您不应该更新Vector。应该直接对ListModel进行更改,然后表将自动重新绘制自身。
在我的REST API中,我有一个过滤器,该过滤器检查每个请求,以查看令牌是否是原样。下面是代码。 当用户登录到应用程序时,将调用上述代码。但是,令牌将在60分钟内过期。我知道,在令牌过期后,要么我必须带用户返回登录屏幕,要么刷新令牌。我把这里和这里的建议都看了一遍 但我不明白以下几点。 如何分配并将此令牌发送回用户?当前,当用户登录时,他将获得令牌并将其保存在一个变量中。为了使刷新的令牌工作,我
如何在更改jPanels高度后刷新它?在我编译代码之后,它确实显示了它,但是在我单击两次random按钮(我使用random按钮将高度更改为随机数)之后,它并没有以我想要的方式显示它。 还有安托赫的事。jPanel是颠倒的。我该怎么改变呢? 下面是我到目前为止编写的代码:
我有一个非常简单的窗口,它包含一个按钮:。 在main函数中,我设置了我的并且在按钮监听器中,我想关闭窗口,所以我将可见性设置为false:之后,我执行以防止在多次运行程序时可能出现的内存泄漏。 我有两个问题: 在上述情况下,我真的需要吗? 如果我有这个作为
问题内容: 我正在使用Java进行项目,因此需要在单击特定按钮后重新加载整个程序。这该怎么做? 问题答案: 尝试 如果仍然无法使用,请在完成上述步骤后尝试
当我单击一个按钮(刷新页面中的数据,释放缓存)主页时,我想刷新页面我的主页中有一个列表。有一个功能可以更改列表上的项目。但当我更改项目并重定向到主页时,它会显示以前的值,直到刷新页面为止,我只想在按下按钮时刷新(清除主页上的缓存)。控制器处于$状态。go(“应用程序订阅”) 我写了这个。如何更改它?