Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Java]Swing, repaint
Forum PHP.pl > Forum > Przedszkole
Gość
Witam. Mam problem, mianowicie chciałbym użyć ponownie funkcji paint przy wykonaniu danej metody.

  1. public void setError(String s)
  2. {
  3. removeAll();
  4. err = s;
  5. repaint();
  6. validate();
  7. }


zadziała, dopiero gdy zmienie rozdzielczość ekranu lub zminimalizuję i maksymalizuję ekno programu...
gdy do samej metody paint(Graphics g) wrzucę repaint(), ona odświeża się w nieskończoność. gdy wrzucę tam warunek do repaint(), dzieje się to samo, co po wywołaniu setError()
mch.frnc
Zastanawiające, że pytasz o Javę w dziale Przedszkole na forum o PHP tongue.gif

Anyway, co dokładnie chcesz odświeżać? Jaki element okna, jakiś jpanel, jframe, całe okno? I co wywołuje metodę setError(), jakieś wciśnięcie klawisza czy inna akcja?
Gość
chcę odświeżyć całe okno..
działa to tak:
jest JPanel, po kliknięciu na niego jest funkcja z innej klasy. Ona, w przypadku błędu wywołuje setError
Crozin
1. Dlaczego nie skorzystasz ze standardowego JLabel? W dodatku jego metoda setText() jest thread-safe co zapewne ułatwiłoby Ci nieco życie.
2. http://www.oracle.com/technetwork/java/painting-140037.html
3. Najprawdopodobniej powinieneś nadpisać metodę paintComponent(), nie paint().
4. Wydaje mi się, że nie do końca rozumiesz działanie metod [re|in]validate().
5.
  1. import java.awt.BorderLayout;
  2. import java.awt.Color;
  3. import java.awt.Dimension;
  4. import java.awt.Graphics;
  5. import java.util.Timer;
  6. import java.util.TimerTask;
  7.  
  8. import javax.swing.JFrame;
  9. import javax.swing.JPanel;
  10. import javax.swing.SwingUtilities;
  11.  
  12.  
  13. public class SwingRepaintTest {
  14. private static class MyPanel extends JPanel {
  15. private static final long serialVersionUID = 1L;
  16.  
  17. private String err = "";
  18.  
  19. public void setError(String err) {
  20. this.err = err;
  21.  
  22. invalidate();
  23. repaint();
  24. }
  25.  
  26. @Override
  27. protected void paintComponent(Graphics g) {
  28. super.paintComponent(g);
  29.  
  30. g.setColor(Color.RED);
  31. g.drawString("Err: " + err, 5, 25);
  32. }
  33. }
  34.  
  35. public static void main(String[] args) throws InterruptedException {
  36. final JFrame frame = new JFrame("Hello");
  37. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  38.  
  39. final MyPanel panel = new MyPanel();
  40. panel.setPreferredSize(new Dimension(200, 50));
  41.  
  42. frame.getContentPane().setLayout(new BorderLayout());
  43. frame.getContentPane().add(panel, BorderLayout.CENTER);
  44.  
  45. SwingUtilities.invokeLater(new Runnable() {
  46. @Override
  47. public void run() {
  48. frame.pack();
  49. frame.setVisible(true);
  50. }
  51. });
  52.  
  53. new Timer().schedule(new TimerTask() {
  54. @Override
  55. public void run() {
  56. panel.setError(String.valueOf(System.currentTimeMillis()));
  57. }
  58. }, 1000, 1000);
  59. }
  60. }
6. Opisz dokładniej co chciałbyś uzyskać - bo na pierwszy rzut oka zbierasz się do tego od złej strony.
Gość
mój kod wygląda tak:
  1. public void drawtext(Graphics g, String text, int x, int y, Color color) {
  2. g.setColor(color);
  3. g.setFont(new Font(null, 1, 16));
  4. FontMetrics f = g.getFontMetrics();
  5. g.drawString(text, x - f.stringWidth(text) / 2, y - f.getHeight() * 2);
  6. }
  7.  
  8. public void paint(Graphics g) {
  9. Image bg = null;
  10. try {
  11. bg = ImageIO.read((net.minecraft.LoginForm.class).getResource("bg.png"));
  12. } catch (IOException e) {
  13. e.printStackTrace();
  14. }
  15.  
  16. g.drawImage(bg, 0, 0, null);
  17.  
  18. drawtext(g, "Tytuł", 237, 320, Color.WHITE);
  19.  
  20. drawtext(g, err, 237, 340, Color.RED);
  21. System.out.println(err);
  22.  
  23. drawtext(g, "Linijka 1", 97, 382, Color.WHITE);
  24. drawtext(g, "Linijka 2", 97, 422, Color.WHITE);
  25.  
  26.  
  27. Image button = null; //169x40
  28. try {
  29. button = ImageIO.read((net.minecraft.LoginForm.class).getResource("button.png"));
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. }
  33.  
  34. g.drawImage(button, 67, 399, null);
  35. g.drawImage(button, 241, 399, null);
  36. drawtext(g, "Przycisk 1", 153, 465, Color.BLACK);
  37. drawtext(g, "Przycisk 2", 327, 465, Color.BLACK);
  38.  
  39. grafika = g;
  40. }
  41.  
  42. public void setError(String s) {
  43. err = s;
  44. //add(buildLoginPanel());
  45.  
  46. invalidate();
  47. repaint();
  48. }



Chodzi mi o ponowne wywołanie paint(), by narysowany tekst (ten, który rysuje zmienną err) zmienił się
Crozin
OK, z tego co widzę posiadasz komponent, który ma jakieś tło, a w jego wnętrzu znajdują się trzy linijki normalnego tekstu, linijka tekstu na błąd oraz dwa przyciski o własnym tle. Te wszystkie elementy możesz - i powinieneś - utworzyć przy pomocy standardowych komponentów JPanel, JLabel oraz JButton.
1. Ustawienie tła dla JPanel jest bardzo proste - możesz jednak skorzystać z bardziej uniwersalnego podejścia.
2. Jeżeli chodzi o przyciski to http://stackoverflow.com/questions/4585867...sparent-jbutton + JButton.setIcon().
3. Użycie standardowych kontrolek zamiast własnego rysowania wszystkiego samemu ma właściwie same zalety.

PS. Tak jak pisałem, w obecnym kodzie powinieneś nadpisać paintComponent(), nie paint(), a w jego wnętrzu wywołać na początku super.paintComponent(g).
Gość
Kiedy używam paintComponents, dzieje się to samo co z paint..
Crozin
paintComponent() i paintComponents() to dwie zupełnie inne rzeczy. Pokaż SSCCE.
Gość
LauncherFrame.java
  1. package net.minecraft;
  2. import java.awt.*;
  3. import java.awt.event.WindowAdapter;
  4. import java.awt.event.WindowEvent;
  5.  
  6.  
  7. public class LauncherFrame extends Frame
  8. {
  9. private static final long serialVersionUID = 1L;
  10. public LoginForm loginForm;
  11.  
  12. public LauncherFrame()
  13. {
  14. setBackground(Color.BLACK);
  15.  
  16. loginForm = new LoginForm(this);
  17. add(loginForm);
  18. loginForm.setPreferredSize(new Dimension(854, 480));
  19. pack();
  20. setLocationRelativeTo(null);
  21.  
  22. addWindowListener(new WindowAdapter() {
  23.  
  24. public void windowClosing(WindowEvent windowevent)
  25. {
  26. System.exit(0);
  27. }
  28. });
  29.  
  30. }
  31. public void doSomething()
  32. {
  33. LoginForm LoginForm = new LoginForm(null);
  34. System.out.println("a");
  35. LoginForm.setError("Błąd.");
  36. }
  37. public static void main(String args[])
  38. {
  39. LauncherFrame launcherframe = new LauncherFrame();
  40. launcherframe.setVisible(true);
  41. }
  42.  
  43. }





LoginForm.java
  1. package net.minecraft;
  2.  
  3. import java.awt.*;
  4. import java.awt.event.MouseEvent;
  5. import java.awt.event.MouseListener;
  6. import java.io.*;
  7. import javax.imageio.ImageIO;
  8.  
  9.  
  10. public class LoginForm extends Panel
  11. {
  12.  
  13. private static final long serialVersionUID = 1L;
  14. private static String err = "";
  15. private LauncherFrame launcherFrame;
  16.  
  17. public LoginForm(LauncherFrame launcherframe)
  18. {
  19. launcherFrame = launcherframe;
  20. GridBagLayout gridbaglayout = new GridBagLayout();
  21. setLayout(gridbaglayout);
  22. this.addMouseListener(new MouseListener() {
  23. @Override
  24. public void mouseClicked(MouseEvent e) {
  25. launcherFrame.doSomething();
  26. }
  27.  
  28. @Override
  29. public void mouseEntered(MouseEvent e) {
  30. // TODO Auto-generated method stub
  31.  
  32. }
  33.  
  34. @Override
  35. public void mouseExited(MouseEvent e) {
  36. // TODO Auto-generated method stub
  37.  
  38. }
  39.  
  40. @Override
  41. public void mousePressed(MouseEvent e) {
  42. // TODO Auto-generated method stub
  43.  
  44. }
  45.  
  46. @Override
  47. public void mouseReleased(MouseEvent e) {
  48. // TODO Auto-generated method stub
  49.  
  50. }
  51. });
  52. }
  53.  
  54. public void drawtext(Graphics g, String text, int x, int y, Color color) {
  55. Font font = new Font(null, 1, 16);
  56. g.setColor(color);
  57. g.setFont(font);
  58. FontMetrics f = g.getFontMetrics();
  59. g.drawString(text, x - f.stringWidth(text) / 2, y - f.getHeight() * 2);
  60. }
  61.  
  62. public void paint(Graphics g)
  63. {
  64. paintComponent(g);
  65. }
  66.  
  67. public void paintComponent(Graphics g)
  68. {
  69. super.paintComponents(g);
  70.  
  71. Image bg = null;
  72. try {
  73. bg = ImageIO.read((net.minecraft.LoginForm.class).getResource("bg.png"));
  74. } catch (IOException e) {
  75. e.printStackTrace();
  76. }
  77. g.drawImage(bg, 0, 0, null);
  78.  
  79. drawtext(g, "Tytuł", 237, 320, Color.WHITE);
  80. drawtext(g, err, 237, 340, Color.RED);
  81.  
  82. drawtext(g, "Linia 1", 97, 382, Color.WHITE);
  83. drawtext(g, "Linia 2", 97, 422, Color.WHITE);
  84.  
  85. }
  86.  
  87. public void setError(String s)
  88. {
  89. err = s;
  90. invalidate();
  91. repaint();
  92.  
  93. }
  94. }



bg.png może być obrazem z czarnym tłem wymiary 854x480
gotowy projekt w zip:
http://www.speedyshare.com/aZc9G/test.zip
Crozin
Kilka błędów:
1. Korzystasz bezpośrednio z AWT zamiast ze Swinga.
2. Odpalasz kod odpowiedzialny za UI w głównym wątku programu czego nie powinno się robić. Google: Java EventDispatchThread, SwingUtilitiles.invokeLater().
3. Jeżeli nadpisujesz jakąś metodę z interfejsu Swinga czy AWT powinieneś niemal zawsze wywołać tę samą metodę z klasy nadrzędnej (super.nazwaMetody()).
4. Jeżeli nadpisujesz jakąś metodę zawsze dodawaj adnotację @Override - uchroni Cię ona przed głupimi błędami. Tutaj przykładowo założyłem, że korzystasz ze Swinga zamiast AWT i zasugerowałem nadpisanie metody paintComponent(Graphics), a ta metoda istnieje wyłącznie w Swingu. W efekcie Twój kod w ogóle się nie wykonywał. W przypadku AWT powinieneś nadpisywać właśnie metodę paint().
5. By wymusić zaktualizowanie interfejsu wystarczy wywołanie repaint(), jednakże dla ciężkich komponentów (m. in. Panel czy Frame) ta metoda jedynie ustawia wewnętrzną flagę, zaś samo przemalowanie może nastąpić dużo później (patrz dokumentacja).

Bezpośrednio w AWT nie projektowałem nigdy interfejsu i nie wiem jak wymusić przemalowanie ciężkich komponentów - odpowiedź zapewne będzie tutaj: http://www.oracle.com/technetwork/java/index.html

Kilka uwag:
1. Zamiast implementować cały interfejs MouseListener, możesz skorzystać z dziedziczenia po anonimowej klasie MouseAdapter i nadpisać w niej jedynie pożądane metody. Tak jak to zrobiłeś w przypadku listenera dla okna (WindowAdapter).
2. Metoda z głównej klasy, która ustawia błędy jest wywoływana z poziomu wątku od UI, stąd powinna zawierać jedynie lekki kod. Jeżeli chciałbyś tam wrzucić jakieś bardziej skomplikowane zadanie, powinieneś to zrobić w osobnym wątku by interfejs programu nie zawiesił się. Google: SwingWorkers.

Tutaj masz przykład jak można to zrobić normalnie, wykorzystując JLabela oraz nadpisując paintComponent()
  1. package net.minecraft;
  2.  
  3. import javax.swing.JFrame;
  4. import javax.swing.SwingUtilities;
  5.  
  6. public class FixedLauncherFrame extends JFrame {
  7. private static final long serialVersionUID = 1L;
  8.  
  9. private FixedLoginForm loginForm;
  10.  
  11. private FixedLauncherFrame() {
  12. loginForm = new FixedLoginForm(this);
  13.  
  14. setContentPane(loginForm);
  15. }
  16.  
  17. public void doSomething(boolean useLabel) {
  18. if (useLabel) {
  19. loginForm.errorLabel.setText("Blah: " + System.currentTimeMillis());
  20. } else {
  21. loginForm.errorMessage = "Blah: " + System.currentTimeMillis();
  22.  
  23. loginForm.repaint();
  24. }
  25. }
  26.  
  27. public static void main(String[] args) {
  28. SwingUtilities.invokeLater(new Runnable() {
  29. @Override
  30. public void run() {
  31. FixedLauncherFrame frame = new FixedLauncherFrame();
  32. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  33.  
  34. frame.pack();
  35. frame.setLocationRelativeTo(null);
  36. frame.setResizable(false);
  37. frame.setVisible(true);
  38. }
  39. });
  40. }
  41. }
  1. package net.minecraft;
  2.  
  3. import java.awt.BorderLayout;
  4. import java.awt.Color;
  5. import java.awt.Dimension;
  6. import java.awt.Graphics;
  7. import java.awt.Image;
  8. import java.awt.event.MouseAdapter;
  9. import java.awt.event.MouseEvent;
  10. import java.io.IOException;
  11.  
  12. import javax.imageio.ImageIO;
  13. import javax.swing.JLabel;
  14. import javax.swing.JPanel;
  15. import javax.swing.SwingUtilities;
  16.  
  17. public class FixedLoginForm extends JPanel {
  18. private static final long serialVersionUID = 1L;
  19.  
  20. public String errorMessage;
  21. public JLabel errorLabel = new JLabel("");
  22.  
  23. private final FixedLauncherFrame launcher;
  24.  
  25. private Image backgroundImage;
  26.  
  27. public FixedLoginForm(FixedLauncherFrame fixedLauncherFrame) {
  28. super(new BorderLayout());
  29.  
  30. this.launcher = fixedLauncherFrame;
  31.  
  32. try {
  33. backgroundImage = ImageIO.read(getClass().getResourceAsStream("bg.png"));
  34. } catch (IOException e1) { }
  35.  
  36. setForeground(Color.WHITE);
  37. setPreferredSize(new Dimension(854, 480));
  38.  
  39. errorLabel.setForeground(Color.RED);
  40.  
  41. add(errorLabel, BorderLayout.LINE_END);
  42.  
  43. addMouseListener(new MouseAdapter() {
  44. @Override
  45. public void mouseClicked(MouseEvent e) {
  46. if (SwingUtilities.isLeftMouseButton(e)) {
  47. launcher.doSomething(true);
  48. } else {
  49. launcher.doSomething(false);
  50. }
  51. }
  52. });
  53. }
  54.  
  55. @Override
  56. protected void paintComponent(Graphics g) {
  57. super.paintComponent(g);
  58.  
  59. if (backgroundImage != null) {
  60. g.drawImage(backgroundImage, 0, 0, getWidth(), getHeight(), this);
  61. }
  62.  
  63. g.setColor(getForeground());
  64. g.drawString("Test: " + System.currentTimeMillis(), 50, 50);
  65.  
  66. if (errorMessage != null) {
  67. g.setColor(Color.RED);
  68. g.drawString("Err: " + errorMessage, 50, 75);
  69. }
  70. }
  71. }
PS. Ten kod miesza ze sobą logikę aplikacji z jej interfejsem, co przy większych aplikacjach jest bardzo złą praktyką.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.