有关Linux上的getBounds()和setBounds()的bug_id = 4806603的解决方法? [英] Workaround for bug_id=4806603 regarding getBounds() and setBounds() on Linux?

查看:36
本文介绍了有关Linux上的getBounds()和setBounds()的bug_id = 4806603的解决方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Linux平台上,Frame :: getBounds和Frame :: setBounds不一致.这已经在2003(!)中进行了报道,请参见此处:

On the Linux platform, Frame::getBounds and Frame::setBounds do not work consistently. This has already been reported in 2003(!), see here:

http://bugs.java.com/bugdatabase/view_bug.do?bug_id = 4806603

为方便起见,我简化了导致错误的声明代码,并将其粘贴为:

For convenience, I have simplified the stated code that results in a bug and paste it as:

import java.awt.Button;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/** Demonstrates a bug in the java.awt.Frame.getBounds() method.
 * @author Mirko Raner, PTSC
 * @version 1.0 (2003-01-22) **/
public class GetBoundsBug extends Frame implements ActionListener {
  public static void main(String[] arg) {
    GetBoundsBug frame = new GetBoundsBug();
    Button button = new Button("Click here!");
    button.addActionListener(frame);
    frame.add(button);
    frame.setSize(300, 300);
    frame.setVisible(true);
  }

  @Override
  public void actionPerformed(ActionEvent event) {
    Rectangle bounds = getBounds();
    bounds.y--;
    setBounds(bounds);
    bounds.y++;
    setBounds(bounds);
  }
}

异常行为::单击按钮后,窗口将稍微移到下方!(在我的系统上,每次点击像素为28像素.)

Unexpected behavior: Upon clicking the button the window is shifted slightly below! (On my system by 28 pixels each click.)

以下是屏幕录像: https://youtu.be/4qOf99LJOf8

这种行为已经存在了13年以上,所以官方可能不会有任何改变.

This behavior has been around for 13+ years, so probably there won't be any change from the official side.

有人对此错误有解决方法吗?具体来说,我想在所有平台上可靠地将窗口/框架/对话框存储和还原到以前的位置.

Does anybody have a workaround for this bug? Specifically, I would like to store and restore the window/frame/dialog at the previous location reliably on all platforms.

PS:我的Java安装是 Oracle 在Ubuntu 16 Linux上对于amd64的 jdk1.8.0_102 .自从我最近从Windows迁移到Ubuntu以来,我知道在Windows上,上面的代码可以按预期工作.

PS: My java installation is jdk1.8.0_102 for amd64 by Oracle on Ubuntu 16 Linux. Since I recently migrated from Windows to Ubuntu, I know that on Windows, the code above works as expected.

使用SwingWorker对Swing进行调整会产生相同的效果:

The adaptation to Swing using SwingWorker produces the same effect:

import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingWorker;

public class GetBoundsBug extends JFrame implements ActionListener {
  public static void main(String[] arg) {
    GetBoundsBug myJFrame = new GetBoundsBug();
    JButton myJButton = new JButton("Click here!");
    myJButton.addActionListener(myJFrame);
    myJFrame.setContentPane(myJButton);
    myJFrame.setSize(300, 300);
    myJFrame.setVisible(true);
  }

  @Override
  public void actionPerformed(ActionEvent event) {
    SwingWorker<Void, Void> mySwingWorker = new SwingWorker<Void, Void>() {
      @Override
      public Void doInBackground() {
        Rectangle myRectangle = getBounds();
        myRectangle.y--;
        setBounds(myRectangle);
        myRectangle.y++;
        setBounds(myRectangle);
        return null;
      }
    };
    mySwingWorker.execute();
  }
}

推荐答案

只是一个附加说明.我注意到您的代码在事件调度线程上做不到很多.Java的所有绘图API都是按设计单线程的,这意味着除非将GUI更新分派给事件分派线程,否则不应期望您的应用程序正常工作.

Just an additional note. I noticed that your code failed to do very much on the Event Dispatch Thread. All of Java's drawing APIs are single threaded by design, meaning that your application should not be expected to work correctly unless you dispatch GUI updates to the Event Dispatch Thread.

这意味着您需要(在主目录中)创建一个新的Runnable,该Runnable在评估后将显示您的小部件,并将其提交给EDT.

This means you need to (in your main) create a new Runnable that when evaluated will present your widgets, and submit that to the EDT.

此外,您的动作侦听器会更新动作中的组件状态,从而绕过重绘请求,并忽略了确保分发给EDT所需的典型安全性.

Also, your action listener updates the component state within the action, bypassing the repaint request and ignoring the typical safeties required to ensure dispatch to the EDT.

在这两种方式中,您编写的代码在Java环境中都不是有效的GUI代码,并且您识别出的错误可能与您的行为无关,因为您的程序在甚至不知道是否该错误会对其造成影响.

In both of these ways, you code is not valid GUI code in a Java environment, and the bug that you identify may have nothing to do with your behavior, as your program is violating the GUI toolkit design before you even know if the bug impacts it.

此外,awt仅包装组件.如果这些组件在撒谎,那么撒谎就会渗入Java中.对此无能为力(但我不再认为这是主要要担心的事情).如果您不喜欢它,请使用Swing,这是一个更加理智/稳定的环境.

Also, awt only wraps components. If the components lie, then the lie trickles into Java. Not much can be done about that (but I no longer think it's the primary thing to worry about). If you don't like that, use Swing, which is a much more sane / stable environment.

这篇关于有关Linux上的getBounds()和setBounds()的bug_id = 4806603的解决方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆