2016-08-22 8 views
7

Na platformie Linux, Frame :: getBounds i Frame :: setBounds nie działają konsekwentnie. (!) To już zostało zgłoszone w 2003 roku, patrz tutaj:Obejście problemu bug_id = 4806603 dotyczące getBounds() i setBounds() w systemie Linux?

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

Dla wygody, mam uproszczona podanej kod, który powoduje błędu i wkleić go jako:

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); 
    } 
} 

Nieoczekiwane zachowanie: Po kliknięciu przycisku okno jest przesunięte nieco poniżej! (. W moim systemie o 28 pikseli każdy klik)

Oto nagranie ekranu: https://youtu.be/4qOf99LJOf8

To zachowanie zostało około 13+ lat, więc prawdopodobnie nie będzie żadnych zmian z oficjalnej strony.

Czy ktoś ma obejście tego błędu? W szczególności chciałbym przechowywać i przywracać okno/ramkę/dialog w poprzedniej lokalizacji niezawodnie na wszystkich platformach.

PS: Moja instalacja java jest jdk1.8.0_102 dla amd64 przez Oracle na Ubuntu 16 Linux. Odkąd przeprowadziłem migrację z systemu Windows do Ubuntu, wiem, że w systemie Windows powyższy kod działa zgodnie z oczekiwaniami.

Adaptacja do Swing za pomocą SwingWorker daje ten sam efekt:

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(); 
    } 
} 
+0

Myślę, że doszedłeś do wniosku, że konkretny błąd jest tym, co widzisz. Wspomniany błąd dotyczy gry na menadżerze Enlightenment Window (e17), który został wydany 19 lat temu, a nawet nie jest dostarczany z Ubuntu 16 Linux (według mojej wiedzy). –

+0

mój system używa menedżera okien: Compiz – datahaki

+0

Następnie błąd specyficzny dla e17 nie dotyczy ciebie. Tak jak błąd specyficzny dla OSX nie dotyczy systemu Windows. Błąd, o którym wspomniałeś, jest sprzeczny z systemem okienkowym e17, coś, co miałem dużo zabawy dostosowywania prawie 20 lat temu. Bardzo, bardzo niewielu ludzi go używa teraz, a powodem, dla którego nie zostało to naprawione, było to, że 13 lat temu był to martwy projekt. e20 to aktualna wersja, ale nie jestem pewien, czy jest stabilny. Podsumowując, źle zinterpretowałeś błąd, który możesz zastosować, ale tak nie jest, jest on w 100% niezwiązany z twoim problemem. –

Odpowiedz

1

Cóż, w oryginalnym wejściem bazy błąd ten jest oznaczony jako „Will not fix” i wyjaśnione jako dziwactwo w menedżerze okien, zamiast JDK.

Jakiego menedżera okien używasz?

+0

Menedżer okien: Compiz. Mam podobny problem z JavaFx, który jest zamieszczony tutaj: http://stackoverflow.com/questions/39086597/first-call-to-javafx-stagesety-inconsistent-on-linux-workaround – datahaki

1

Tylko dodatkowa uwaga. Zauważyłem, że Twój kod nie zrobił zbyt wiele w wątku wysyłki zdarzeń. Wszystkie interfejsy API rysowania Java są projektowane w jednym wątku, co oznacza, że ​​aplikacja nie powinna działać prawidłowo, chyba że wyślesz aktualizacje GUI do wątku wywołującego zdarzenia.

Oznacza to, że powinieneś (w swojej głównej postaci) utworzyć nowy zestaw Runnable, który oceniany, przedstawi twoje widżety i przekaże je do EDT.

Ponadto program nasłuchujący działania aktualizuje stan komponentu w ramach działania, pomijając żądanie ponownego malowania i ignorując typowe zabezpieczenia wymagane do wysłania do EDT.

W obu tych przypadkach kod jest nieprawidłowym kodem GUI w środowisku Java, a wykryty błąd może nie mieć nic wspólnego z Twoim zachowaniem, ponieważ Twój program narusza projekt zestawu narzędzi GUI, zanim jeszcze się zorientujesz. jeśli błąd ma na to wpływ.

Ponadto, awt tylko zawija komponenty. Jeśli składniki leżą, to kłamstwo przechodzi do Javy. Niewiele można z tym zrobić (ale już nie myślę, że to jest najważniejsze). Jeśli ci się to nie podoba, użyj Swinga, które jest o wiele bardziej rozsądnym/stabilnym środowiskiem.

+0

Dołączyłem do pytania o adaptację kodu używa huśtawki. Tam spróbowałem twojej rady za pomocą SwingWorker, ale bez powodzenia. Proszę poinformować, jeśli używam go niepoprawnie ... dzięki! – datahaki

+0

Należy zwrócić uwagę na samouczki dotyczące współbieżności i Swing. Dotyczy to również AWT. Oto link https://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html –

Powiązane problemy