Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You project is suffering from a number of really basic misconceptions about how painting in Swing works.</p> <p>Because (at the time I tested it) you hadn't provided the full code, I had to make some assumptions.</p> <p>Your expection is that the content pane of the <code>JFrame</code> is using a <code>null</code> layout. I'd find it difficult to see how you would mange this and have other components on the frame. In any case, I would isolate a separate container to act as the "main" view for your <code>Pocitadlo</code>. This allows you to continue using layout managers to manage the other components as well.</p> <p>I'm a little concerned that you trap the entire <code>Pocitadlo</code> generation code in a <code>try-catch</code> simply to catch a numeric conversion. Since you've already applied a default value, it would be reasonable to trap the conversion in its own <code>try-catch</code> and ignore it if it fails (displaying a message as required). Now I'm coming in from the outside, so you may see a need for this, it just caught my eye...</p> <p>Your <code>valueTimer</code> <code>actionPerformed</code> code is slightly erronous, as it's possible for the <code>blinkTimer</code> to continue running even after the <code>valueTimer</code> has completed. I corrected this by merging two of you <code>if</code> statements into a <code>if-else</code> statement instead...</p> <pre><code>if (value == 0 &amp;&amp; actionListener != null) { isRunning = false; valueTimer.stop(); actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "counterFinished")); blinkTimer.stop(); } else if (value &lt; maxValue / 2 &amp;&amp; !blinkTimer.isRunning()) { blinkTimer.start(); } </code></pre> <p>I, personally, would use a <code>JPanel</code> over a <code>JComponent</code>. <code>JPanel</code> is opaque to start with.</p> <p>The main problem is in you <code>paintComponent</code> method.</p> <ol> <li>You should always call <code>super.paintComponent</code>, and on opaque components it should be called first.</li> <li>You seem to think you have to correct for the components position when painting, for example <code>g.fillRect(getX(), getY(), getWidth(), getHeight());</code>. This is actually wrong. The graphics context has already been translated so that the x/y position of the component/graphics is now equal to 0x0. Have a read through <a href="http://www.oracle.com/technetwork/java/painting-140037.html" rel="nofollow">Painting in AWT and Swing</a> for a better explanation, but basically, this means, the top/left corner of you paint area is now 0x0.</li> <li>You seem to think that text is painted from the top/left corner of the first character. This is actually wrong. Text is painted along it's base line. You need to compenstate for this by adjusting the y-position by the <code>Font</code>s ascent value.</li> </ol> <p>.</p> <pre><code>import java.awt.BorderLayout; import java.awt.Color; import java.awt.EventQueue; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.GridBagConstraints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; import java.util.Random; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class TestRepaint01 { public static void main(String[] args) { new TestRepaint01(); } public TestRepaint01() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } MainFrame frame = new MainFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(200, 200); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class MainFrame extends javax.swing.JFrame implements ActionListener { ArrayList&lt;Pocitadlo&gt; poc; Random rnd; private JPanel body; /** * Creates new form frmMain */ public MainFrame() { setLayout(new BorderLayout()); poc = new ArrayList&lt;Pocitadlo&gt;(); rnd = new Random(); body = new JPanel(null); add(body); JButton btn = new JButton("Add"); btn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { int val, x, y; val = 20; x = (getWidth() / 2) - 10 + rnd.nextInt(20); y = (getHeight() / 2) - 10 + rnd.nextInt(20); // try { // val = Integer.parseInt(txtCounterValue.getText()); Pocitadlo tmp = new Pocitadlo(val, x, y, getFont()); tmp.addActionListener(MainFrame.this); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.weightx = 1; gbc.fill = GridBagConstraints.HORIZONTAL; poc.add(tmp); tmp.start(); body.add(tmp); body.repaint(); setTitle("Počet počítadiel: " + getComponentCount()); // } catch (Exception e) { // JOptionPane.showMessageDialog(this, "Nesprávne zadaná alebo prázdna hodnota počítadla. Hodnota musí byť celé číslo.", "Chyba", JOptionPane.ERROR_MESSAGE); // } } }); add(btn, BorderLayout.SOUTH); } @Override public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("counterFinished")) { System.out.println("Counter finished"); Pocitadlo tmp = (Pocitadlo) e.getSource(); poc.remove(tmp); this.setTitle("Počet počítadiel: " + poc.size()); body.remove(tmp); // body.revalidate(); body.repaint(); } } } public class Pocitadlo extends JPanel implements MouseListener, ActionListener { private int maxValue, value; private Boolean isRunning, isDisplayed; private Timer valueTimer, blinkTimer; private ActionListener actionListener; private Font font; public Pocitadlo(int timeout, int x, int y, Font f) { isRunning = false; isDisplayed = true; maxValue = value = timeout; valueTimer = new Timer(1000, this); valueTimer.setActionCommand("valueTimer"); blinkTimer = new Timer(200, this); blinkTimer.setActionCommand("blinkTimer"); this.setBounds(x, y, 100, 50); } @Override public void removeNotify() { super.removeNotify(); stop(); blinkTimer.stop(); } public void start() { isRunning = true; valueTimer.start(); } public void stop() { isRunning = false; valueTimer.stop(); } @Override public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("valueTimer")) { value--; System.out.println("value = " + value); if (actionListener != null) { repaint(); actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "counterTick")); } if (value == 0 &amp;&amp; actionListener != null) { isRunning = false; valueTimer.stop(); actionListener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "counterFinished")); blinkTimer.stop(); } else if (value &lt; maxValue / 2 &amp;&amp; !blinkTimer.isRunning()) { blinkTimer.start(); } } if (e.getActionCommand().equals("blinkTimer")) { System.out.println("Blink"); isDisplayed = !isDisplayed; repaint(); } } public void addActionListener(ActionListener listener) { actionListener = listener; } @Override public void mouseClicked(MouseEvent e) { value += 5000; if (value &gt; maxValue) { value = maxValue; } repaint(); } @Override public void mouseExited(MouseEvent e) { } @Override public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.red); // location bad g.fillRect(0, 0, getWidth(), getHeight()); if (isDisplayed) { g.setColor(Color.green); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(Color.black); //g.setFont(font); FontMetrics fm = g.getFontMetrics(); g.drawString(value + "/" + maxValue, 0, fm.getAscent()); } g.drawRect(0, 0, getWidth() - 1, getHeight() - 1); } @Override public void mousePressed(MouseEvent e) { } @Override public void mouseReleased(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { } } } </code></pre> <p>None of the problems you've encountered are super critical (sure, you program doesn't do what you want) and suggest that you've reached a pinnacle moment in your code abilities. I say this, because I made the exact same mistakes... ;)</p> <p>Take a closer look at <a href="http://docs.oracle.com/javase/tutorial/2d/index.html" rel="nofollow">2D Graphics</a> and <a href="http://docs.oracle.com/javase/tutorial/uiswing/painting/" rel="nofollow">Custom Painting</a></p> <p>I'd also take a look at <a href="http://www.oracle.com/technetwork/java/codeconv-138413.html" rel="nofollow">Code Conventions for the Java Programming Language</a> as you simply annoy people if you don't follow them ;)</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload