?
Solved

Subclassing question...

Posted on 1998-03-12
7
Medium Priority
?
218 Views
Last Modified: 2011-09-20
null
0
Comment
Question by:bjg
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
7 Comments
 
LVL 16

Accepted Solution

by:
imladris earned 100 total points
ID: 1233517
The first thing the multilinebutton does is call multilinelabel's paint method. Shortly AFTER, it calls setBackground. This will "cover" the string.

0
 

Author Comment

by:bjg
ID: 1233518
I also added update(Graphics g) inside the MultiLineLabel.  The problem is that when I process any of the mouseEvents, it seems to just keep repainting or something.  It's hard to explain, but if you want, I could send you the code, and you can test it and see what it is doing.  If this is ok, please send me your email address...
0
 

Author Comment

by:bjg
ID: 1233519
MultiLineLabel.java


import java.awt.*;
import java.util.StringTokenizer;

public class MultiLineLabel extends Canvas
{
      //Alignment Constants
          public static final int LEFT = 0, CENTER = 1, RIGHT = 2;

      protected String             m_label;
      protected int             m_alignment;

         protected int             m_marginWidth = 10;
          protected int             m_marginHeight = 10;
          protected int             m_numLines;
          protected String[]             m_lines;
          protected int[]             m_lineWidths;
          protected int             m_maxWidth;
          protected int             m_lineHeight;
          protected int             m_lineAscent;
          protected boolean             m_measured = false;

      /*** Two versions of the constructor ***/
          public MultiLineLabel(String label, int alignment)
      {
            this.m_label = label;
              this.m_alignment = alignment;
              processLabel();        
          }
   
          public MultiLineLabel(String label)
      {
            this(label, LEFT);
          }
   
      /*** Public Accessor Methods ***/
          public void setLabel(String label)
      {
            this.m_label = label;
              processLabel();
              m_measured = false;
              repaint();
          }
   
          public void setFont(Font f)
      {
            super.setFont(f);
            m_measured = false;
            repaint();
          }
   
          public void setForeground(Color c)
      {
            super.setForeground(c);
              repaint();
          }

      public void setBackground(Color c)
      {      
            super.setBackground(c);
            repaint();
      }
   
          public void setAlignment(int a)
      {
            m_alignment = a;
              repaint();
          }
   
          public String getLabel()
      {
              return m_label;
          }
   
          public int getAlignment()
      {
            return m_alignment;
          }
   
          public Dimension getPreferredSize()
      {
            if (!m_measured)
                  measure();
              return new Dimension(m_maxWidth + 2*m_marginWidth,
                             m_numLines * m_lineHeight + 2*m_marginHeight);
          }
   
          public Dimension getMinimumSize()
      {
            return getPreferredSize();
          }

      public void update(Graphics g)
      {
            System.out.println("in MultiLineLabel().update()");
            paint(g);
      }
   
      /*** Paint the graphics ***/
          public void paint(Graphics g)
      {
            int x, y;
              Dimension size = this.getSize();  
              if (!m_measured)
                  measure();
              y = m_lineAscent + (size.height - m_numLines * m_lineHeight)/2;
              for (int i = 0; i < m_numLines; i++, y += m_lineHeight)
            {
                  switch(m_alignment)
                  {
                            default:
                            case LEFT:      
                              x = m_marginWidth;
                              break;
                            case CENTER:    
                              x = (size.width - m_lineWidths[i])/2;
                              break;
                            case RIGHT:    
                              x = size.width - m_marginWidth - m_lineWidths[i];
                              break;
                  }
                  g.drawString(m_lines[i], x, y);
              }
          }
   
      /***
            This protected method parses through the label and checks
            for new line characters ('\n').  It also stores each line,
            the number of lines, and each line's width.
      ***/      
          protected void processLabel()
      {
            StringTokenizer t = new StringTokenizer(m_label, "\n");
              m_numLines = t.countTokens();
              m_lines = new String[m_numLines];
              m_lineWidths = new int[m_numLines];
              for (int i = 0; i < m_numLines; i++)
                  m_lines[i] = t.nextToken();
          }
   
      /***
            This protected method measures each line to determine the maximum
            width and height of the label.
      ***/
          protected void measure()
      {
            FontMetrics fm = this.getToolkit().getFontMetrics(this.getFont());
              m_lineHeight = fm.getHeight();
              m_lineAscent = fm.getAscent();
              m_maxWidth = 0;
              for (int i = 0; i < m_numLines; i++)
            {
                  m_lineWidths[i] = fm.stringWidth(m_lines[i]);
                  if (m_lineWidths[i] > m_maxWidth)
                        m_maxWidth = m_lineWidths[i];
              }
              m_measured = true;
          }
}
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:bjg
ID: 1233520
Actually, MultiLineButton is called KeyButton

KeyButton.java

import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class KeyButton extends MultiLineLabel
{
          private boolean pressed = true;
          private boolean isOn = false;

      private int width, height;
        private ActionListener actionListener;
          private String actionCommand;

           private Font m_font = new Font("SansSerif", Font.PLAIN, 9);

          private int keyvalue;

          public KeyButton(String label, ActionListener listener, int width,
                        int height, int alignment, int keyvalue)
      {
            super(label, alignment);

            this.width = width;
            this.height = height;
            this.keyvalue = keyvalue;
            this.actionListener = listener;
            this.actionCommand = String.valueOf(keyvalue);
            this.setFont(m_font);
            enableEvents(AWTEvent.MOUSE_EVENT_MASK);
          }

          public KeyButton(String label, ActionListener listener, int width,
                        int height, int keyvalue)
      {
            this(label, listener, width, height, CENTER, keyvalue);
          }
   
          public KeyButton(String label, ActionListener listener, int keyvalue)
      {
            this(label, listener, 30, 30, CENTER, keyvalue);
          }

      public int getKeyValue()
          {
            return keyvalue;
      }

      public void setKeyValue(int newval)
      {
            keyvalue = newval;
      }
   
          public void setKeyOn(boolean yesno)
          {
            isOn = yesno;
            repaint();
          }

          public boolean isKeyOn()
          {
            return isOn;
          }      
   
          public Dimension getPreferredSize()
      {
            if (!super.m_measured) super.measure();
                  return new Dimension(width,height);
          }
   
          public Dimension getMinimumSize()
      {
            return getPreferredSize();
          }

      public void update(Graphics g)
      {
            System.out.println("in KeyButton().update()");
            paint(g);
      }
   
          public void paint(Graphics g)
      {
            super.paint(g);

            int x, y;
              Dimension size = this.getSize();  

            if (isOn)
                  super.setBackground(Color.green);
              else
                  super.setBackground(Color.lightGray);

              if(pressed)
            {
                  //Make the button look like it is pressed.
                    g.setColor(Color.black);
                    g.drawRect(0,0,size.width-1, size.height-1);
              } else
            {
                  //Make the button look like it is raised.
                  g.setColor(Color.darkGray);
                    g.drawRect(0,0,size.width-1, size.height-1);
                  g.drawRect(0,0,size.width-2, size.height-2);
                    g.setColor(Color.white);
                    g.drawRect(1,1,size.width, size.height);
                  g.drawRect(2,2,size.width-2, size.height-2);
              }
          }
   
          public void addActionListener(ActionListener listener)
          {
                actionListener = AWTEventMulticaster.add(actionListener, listener);
            enableEvents(AWTEvent.MOUSE_EVENT_MASK);
          }

      public void removeActionListener(ActionListener listener)
      {
            actionListener = AWTEventMulticaster.remove(actionListener, listener);
         }

      public void setActionCommand(String command)
      {
            actionCommand = command;
      }

      public String getActionCommand()
      {
            return actionCommand;
      }

          public void processMouseEvent(MouseEvent e)
      {
            switch(e.getID())
            {
                      case MouseEvent.MOUSE_PRESSED:
                        pressed = true;
                        this.repaint();
                        break;
                      case MouseEvent.MOUSE_RELEASED:
                        if(actionListener != null)
                        {
                                 actionListener.actionPerformed(new ActionEvent(
                                     this, ActionEvent.ACTION_PERFORMED, actionCommand));
                        }
                        if (pressed)
                                  pressed = false;
                            this.repaint();
                        break;
                      case MouseEvent.MOUSE_ENTERED:
                            if (pressed)
                              pressed = false;
                        this.repaint();
                        break;
                      case MouseEvent.MOUSE_EXITED:
                        if (!pressed)
                                  pressed = true;
                        this.repaint();
                        break;
             }
             super.processMouseEvent(e);
         }
}



0
 
LVL 16

Expert Comment

by:imladris
ID: 1233521
Sorry, I appear to have been a bit too quick off the mark. I thought the setBackground call would floodfill the component with the specified colour. But closer inspection indicates that it is the update method that does that with a fillRect call. And you have correctly overridden the update method.

As for the repeating, the paint method in KeyButton is calling super.setBackground. And the setBackground method in Multilinelabel is calling repaint, which will (shortly) cause paint to be called again etc. etc.

setBackground and -Foreground should not call repaint. In fact there is no apparent need for them to be overridden at all. A call to setBackground will eventually bubble up the inheritance hierarchy far enough for the right thing to occur quite on its own.

0
 

Author Comment

by:bjg
ID: 1233522
Well, I took out the overridden setForeground and setBackground methods, and that has helped a little, but I am still having the problem where when I call mouseEntered() and I want the button to be raised, and then call mouseExited() and want the button to be sunken, it is not processing correctly.  The button's state initially is set to pressed, which makes the button appear pressed or sunken.  When the mouse enters over the button, the button's state is set to not pressed and I repaint(), and when the mouse exits the button, it's state is set to pressed and I repaint again.  Same goes true for mousePressed and mouseReleased.  But once I perform any of these actions, the button stays in the not pressed state.  Why is this happening?
0
 
LVL 16

Expert Comment

by:imladris
ID: 1233523
Sorry, I don't see the answer to that one. Your logic seems reasonably enough. When MOUSE_EXITED occurs the pressed variable will always be made true, and then a repaint is requested. This should cause paint to be executed with the press variable still in the true state. The only thing I can suggest here is to emit a print trail (with System.out.println or some such thing) to verify the execution path and variable states.

0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.
Suggested Courses

719 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question