Adding Custom Method to JButton class - java

I have a Java Application, I am wanting to format a button as either Active or Inactive (Also possibly a hover method).
The code as I would like to implement it:
//Home Tab - Active by default
home = new TabButton();
home.setSize(new Dimension(tabWidth, tabHeight));
home.setFont(getLauncherFont(34));
home.setForeground(Color.white);
home.setText("HOME");
home.setBounds(160, 0, tabWidth, tabHeight);
home.setActive(); --> This Method is what I would like to create
I already have a class to create a JButton for the tab:
package com.anarcist.minemodloaderv1.skin.components;
import java.awt.Color;
import javax.swing.JButton;
/**
*
* #author anarcist
*/
public class TabButton extends JButton {
public TabButton() {
this.setBorderPainted(false);
this.setFocusPainted(false);
this.setContentAreaFilled(true);
this.setBackground(Color.blue);
}
}
I have researched abstract classes. But my TabButton class already extends JButton.
I would like a method like this:
public void setActive(){
this.setBackground(Color.red);
//Any other changes a want to make regularly
}
That can simply be implemented like this home.setActive();
My Question I suppose is: Is it easy enough to implement what I am looking for, or will I have to got the long way and set all attributes manually every time?

What you've described in the post can be done like this:
package com.anarcist.minemodloaderv1.skin.components;
import java.awt.Color;
import javax.swing.JButton;
/**
*
* #author anarcist
*/
public class TabButton extends JButton {
public TabButton() {// initialize
this.setBorderPainted(false);
this.setFocusPainted(false);
this.setContentAreaFilled(true);
this.setBackground(Color.blue);
}
// add your own methods or override JButton methods
public void setActive(){
//Add code
//example: setEnabled(true);
}
}

Related

How do I access this keyword In a different class

am having a problem trying to access this keyword in a different class using Java programming. I have tried Context, class.this but no help yet...
I have created a project using NetBeans gui builder, I want when i click button the form to get disposed...
Main class contains the click event for disposing the JFrame Form
BestQSystems.java:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
CloseWindow.closeWindow();
}
Class to close the JFrame: CloseWindow.java
import java.awt.Toolkit;
import java.awt.event.WindowEvent;
import javax.naming.Context;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author Benson
*/
public class CloseWindow {
public static void closeWindow(){
WindowEvent widnowEvent = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(widnowEvent);
}
}
Am having an error in this line WindowEvent widnowEvent = new WindowEvent(this, WindowEvent.WINDOW_CLOSING); Please advise me on how to access this keyword in a different class.
You can pass a reference to this to the other method. For example:
BestQSystems.java
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
CloseWindow.closeWindow(this);
}
and in the CloseWindow.java
public class CloseWindow {
public static void closeWindow(BestQSystems ref){
WindowEvent widnowEvent = new WindowEvent(ref, WindowEvent.WINDOW_CLOSING);
}
}

JPanel is not updating one of the two pieces of data I need to be updated

I am trying to track all of the supplies stored in a knapsack object and create an interface that shows the supplies update using an observer/observable implementation. For some reason when I run this code, with 2 items in the knapsack, the second item updates and shows expiration date decreasing as time change is triggered. The first one does not change at all, as if it's a static label. Please could someone let me know what I did wrong? Thanks so much for your help in advance! Also, I'm super new to Java programming so please extra information/explanation would be greatly appreciated.
Here is my code:
package view;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import supplies.Supplies;
import model.Adventure;
import model.Knapsack;
public class InventoryView extends JPanel implements Observer{
private Knapsack knapsack;
private Adventure adventure;
private JLabel b;
public InventoryView(Adventure adventure) {
this.adventure=adventure;
this.knapsack=adventure.getSquad().getKnapsack();
for (Supplies supply : knapsack.getSupplies()) {
b=new JLabel(supply.toString());
add(b);
}
knapsack.addObserver(this);
}
#Override
public void update(Observable arg0, Object arg1) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
for (Supplies supply : knapsack.getSupplies()) {
b.setText(supply.toString());
add(b);
}
}
});
}
}
Swing is lazy when it comes to container updates (add/removes), this allows you to execute a number of add/removes in quick succession without fear that the system will grind to a halt while it attempts to update the entire container hierarchy on each call.
Call revalidate and repaint after you have added all your components. Also, make sure that your JPanel is using a layout manager capable of supporting multiple children.
You might consider using a JList or JTable instead

What is an advisable design pattern for switching between GUI pages?

What I don't like about my code below is:
getters are needed for every JButton on each page
the actionPerformed method can quickly become bloated with if-else statements
So, is there a better way to control all GUI actions from a single class?
If I define an actionPerformed method within each respective page (JPanel), each page will need access to instances of the page(s) switched to, and I am trying to avoid using the Singleton pattern for each page...
Here is the code:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
*
* #author Ian A. Campbell
*
*/
public class Controller implements ActionListener {
/**
* instance variables:
*/
private Frame frame;
private OptionPage firstPage;
private FirstOptionPage firstOption;
private SecondOptionPage secondOption;
/**
*
*/
public Controller() {
// instantiating the frame here:
this.frame = new Frame();
/*
* instantiating all pages here:
*
* NOTE: passing "this" because this class
* handles the events from these pages
*/
this.firstPage = new OptionPage(this);
this.firstOption = new FirstOptionPage(this);
this.secondOption = new SecondOptionPage(this);
}
/**
*
*/
public void start() {
this.frame.add(this.firstPage); // adding the first page
// NOTE: these lines prevent blank loading and flickering pages!
this.frame.validate();
this.frame.repaint();
this.frame.setVisible(true);
}
/**
*
* #return the JFrame instantiated from the class Frame
*/
public Frame getFrame() {
return this.frame;
}
#Override
public void actionPerformed(ActionEvent e) {
// the "first option" button from the OptionPage:
if (e.getSource() == this.firstPage.getFirstButton()) {
this.frame.getContentPane().removeAll();
this.frame.getContentPane().add(this.firstOption);
// the "second option" button from the OptionPage:
} else if (e.getSource() == this.firstPage.getSecondButton()) {
this.frame.getContentPane().removeAll();
this.frame.getContentPane().add(this.secondOption);
}
// NOTE: these lines prevent blank loading and flickering pages!
this.frame.validate();
this.frame.repaint();
this.frame.setVisible(true);
}
} // end of Controller
Use a Card Layout. Card Layout Actions adds some extra features that you might find helpful.
You could use card layout, or you could get creative and remove elements. For instance:
panel.remove((JButton)myButton1)); // Remove all of the elements...
panel.add((JButton)myButton2)); // Add the new elements
Of course I wouldn't deal with the java built in GUI at all, IMO the layout designs are horrific. I would much rather use something like "A New Look and Feel" -- http://www.javootoo.com/.

Multiple Jpanel with buttons in one Jframe on MVC, how do I get the actionlistener in my controler ?

this is a homework btw,
I am asked to make a jframe containing multiple jpanels which have buttons and action listeners attached to them. I have to use the MVC model to do it but, since my buttons/actions are in jpanels instead of the jframe, i do not know how to recover them. I wont put down all of my code but, just what is needed to see what I try to do. I want to get the button "ajouter" from panel 3 first to do whatever action:
So this is pannel 3
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import ca.uqam.inf2120.tp2.modele.GestionAbsenceEmployes;
public class RechercherAbsenceP3 extends JPanel {
private GestionAbsenceEmployes aControleur;
private JButton ajouter, modifier, supprimer, afficher, fermer;
FlowLayout gestionnaireComposant;
RechercherAbsenceP3() {
try {
jbInitP3();
} catch (Exception e) {
e.printStackTrace();
}
ajouter.addActionListener(aControleur);
modifier.addActionListener(aControleur);
supprimer.addActionListener(aControleur);
afficher.addActionListener(aControleur);
fermer.addActionListener(aControleur);
}
private void jbInitP3() throws Exception {
gestionnaireComposant = new FlowLayout(FlowLayout.RIGHT);
this.setLayout(gestionnaireComposant);
ajouter = new JButton("Ajouter");
modifier = new JButton("Modifier");
modifier.setEnabled(false);
supprimer = new JButton("Supprimer");
supprimer.setEnabled(false);
afficher = new JButton("Afficher");
afficher.setEnabled(false);
fermer = new JButton("Fermer");
this.add(ajouter);
this.add(modifier);
this.add(supprimer);
this.add(afficher);
this.add(fermer);
}
public JButton getAjouter() {
return ajouter;
}
}
This is the window
package ca.uqam.inf2120.tp2.interfacegraphique;
import java.awt.BorderLayout;
import ca.uqam.inf2120.tp2.interfacegraphique.RechercherAbsenceP3;
import javax.swing.JFrame;
import javax.swing.JPanel;
import ca.uqam.inf2120.tp2.modele.GestionAbsenceEmployes;
public class CreerRechercherAbsence extends JFrame {
private GestionAbsenceEmployes aControleur;
private JPanel absenceP1, absenceP2, absenceP3;
private BorderLayout gestionnaireComposant;
public CreerRechercherAbsence() {
super("Gestionnaire des employés absents");
try {
jbInit();
} catch (Exception ex) {
ex.printStackTrace();
}
aControleur = new GestionAbsenceEmployes(this);
}
void jbInit() throws Exception {
gestionnaireComposant = new BorderLayout(5, 5);
this.getContentPane().setLayout(gestionnaireComposant);
absenceP1 = new RechercherAbsenceP1();
absenceP2 = new RechercherAbsenceP2();
absenceP3 = new RechercherAbsenceP3();
this.getContentPane().add(absenceP1, BorderLayout.NORTH);
this.getContentPane().add(absenceP2, BorderLayout.CENTER);
this.getContentPane().add(absenceP3, BorderLayout.SOUTH);
}
}
now the not finished controler:
package ca.uqam.inf2120.tp2.modele;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import ca.uqam.inf2120.tp1.partie1.adt.impl.ListeAdtArrayListImpl;
import ca.uqam.inf2120.tp2.interfacegraphique.CreerRechercherAbsence;
public class GestionAbsenceEmployes implements ActionListener{
private AbsenceEmploye modele;
private CreerRechercherAbsence vue;
public GestionAbsenceEmployes(CreerRechercherAbsence uneVue) {
this.modele = new AbsenceEmploye();
vue = uneVue;
}
public AbsenceEmploye getModele() {
return modele;
}
#Override
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if(source == vue.getAjouter()) {
}
}
}
When I add the vue.getAjouter() it does not know what it is !!!
What do I do/get wrong ?
The problem is you are calling getAjouter() on CreerRechercherAbsence JFrame instance in your ActionListener where as you'd want to be calling getAjouter() on RechercherAbsenceP3 JPanel instance.
My solution:
Convert your ActionListener class GestionAbsenceEmployes to accept RechercherAbsenceP3 as the parameter so we can call getAjouter() on its instance like so:
class GestionAbsenceEmployes implements ActionListener {
private AbsenceEmploye modele;
private RechercherAbsenceP3 vue;
public GestionAbsenceEmployes(RechercherAbsenceP3 uneVue) {
this.modele = new AbsenceEmploye();
vue = uneVue;
}
public AbsenceEmploye getModele() {
return modele;
}
#Override
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if (source == vue.getAjouter()) {
}
}
}
you would than do:
aControleur = new GestionAbsenceEmployes(absenceP3);
but in order for the above statement to function you must change this:
private JPanel absenceP1, absenceP2,absenceP3;
in CreerRechercherAbsence class to this:
private JPanel absenceP1, absenceP2;
private RechercherAbsenceP3 absenceP3;
because you extend JPanel to add functionality hence the RechercherAbsenceP3 but by declaring it as JPanel you down cast it, thus it does not have access to the methods of extended JPanel RechercherAbsenceP3 and only those of default JPanel.
Some other suggestions:
Do not extend JFrame class unnecessarily
No need for getContentPane.add(..) as add(..) has been diverted to contentPane
Be sure to create and manipulate Swing components on Event Dispatch Thread
Not sure whether the following approach will be considered MVC, or whether it will result in good marks on your assignment.
My "problem" with your current approach is that the reusability is limited to the model, and that it looks difficult to write a decent test case for this code, unless you are prepared to write tests which include the whole view.
When I need to write a Swing application, it seems that I only end up with 2 classes: a model class defining the data and the operations available on that data, and the view class. The view class functions both as view as well as controller. When I have a button as in your example, I would attach an ActionListener to it (or use an Action) which just retrieves the necessary information from the view without any logic. It passes all that information directly to the model side where all the logic is located.
The two main benefits I see in this approach:
I can re-design my view without any problems. If I decide to remove a JButton and provide the user with another mechanism for that same operation, all my changes are limited to the view. I have no dependency on UI elements except in my view class. I see all the "information gathering and passing it to the model" directly in my view class, and due to the implementation of that view this will not affect other classes. Compare that with your code where you have a source == vue.getAjouter() check in a class outside your view.
I can test the model and all its logic without needing my actual view. So I can skip the whole "firing up a Swing UI" in a unit test and still test all my logic. If I want to test the UI (for example to test whether a certain button is disabled when a field is left blank) I can test this separately in an integration test (as having a UI tends to slow down your tests).
What I found a very interesting article in this regard is The humble dialog box
Here is how I would do it. Make GestionAbsenceEmployes a non-static inner class of CreerRechercherAbsence
public class CreerRechercherAbsence extends JFrame {
private GestionAbsenceEmployes aControleur;
private JPanel absenceP1, absenceP2;
private RechercherAbsenceP3 absenceP3;
// code omitted
public CreerRechercherAbsence() {
super("Gestionnaire des employés absents");
try {
jbInit();
} catch (Exception ex) {
ex.printStackTrace();
}
aControleur = new GestionAbsenceEmployes();
}
// code omitted
class GestionAbsenceEmployes implements ActionListener{
private AbsenceEmploye modele;
public GestionAbsenceEmployes() {
this.modele = new AbsenceEmploye();
}
public AbsenceEmploye getModele() {
return modele;
}
#Override
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
if(source == absenceP3.getAjouter()) {
}
}
}
No need to pass this to the constructor and the controller does not need a reference to vue. You get all that for free by making this an inner class. Your controller can access all the member variables of the view. So you can now access the absenseP3 panel with the getAjouter() method.
See http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html for more information on when it makes sense to use inner classes.

Can someone convert this Java code in to Clojure

Can someone convert this into Clojure, I don't know to do the line setMainWindow(argument) like things....
import com.vaadin.Application;
class something {
public void init() {
Window main = new Window("The Main Window");
setMainWindow(main);
addComponent(new WindowOpener("Window Opener", main));
}
}
Update:
package app;
import com.vaadin.Application;
import com.vaadin.ui.Button;
import com.vaadin.ui.Window;
/**
* The Application's "main" class
*/
#SuppressWarnings("serial")
public class MyVaadinApplication extends Application{
private Window window;
#Override
public void init(){
window = new Window("My Vaadin Application");
setMainWindow(window);
window.addComponent(new Button("Click Me"));
}
}
There is a "/lib/vaadin.jar" which contains all "com.vaadin.*" things.
I think setMainWindow(window); is from the extended class. I am not going to write that method.
Literal translation:
(defn init []
(let [main (Window. "The Main Window")]
(setMainWindow main)
(addComponent (WindowOpener. "Window Opener" main))))
Though it doesn't make much sense without the context.
See http://dev.vaadin.com/wiki/Articles/ClojureScripting. Also I would suggest http://www.odesk.com.

Categories