Java GUI application help needed

Get help on programming - C++, Java, Delphi, etc.
Post Reply
PypLaCe
Registered User
Posts: 214
Joined: 19 Apr 2005, 02:00
Location: Johannesburg
Contact:

Java GUI application help needed

Post by PypLaCe »

Hi guys!

I have a Java SE desktop application that I need a bit of help with... The application has a main form (jFrame) that is shown when you run the jar file. On this main form, there are a few buttons that open other windows (also jFrames) that perform specific tasks.

So, for example, the main form might have a button that opens a window to add users on and another button to open a window to edit user information on. (These "secondary" jFrames might open other jFrames)

The problem that I have is that each of these jFrames have their own taskbar item, which causes the taskbar to fill up quite a bit just for this one application. I just want one taskbar item for any ammount of jFrames that might be open.

I know that I can make use of a jFrame with a DesktopPane and then add jInternalFrames to the DesktopPane container, but some of the jFrames that I open from the main jFrame then have to open maybe even more jFrames, and then this becomes a little bit confusing.

Any help/sample code would be much appreciated. BTW, I am using Netbeans 6.5 to develop this app.

Thanks!
RuadRauFlessa
Registered User
Posts: 20576
Joined: 19 Sep 2003, 02:00
Location: Bloodbank

Re: Java GUI application help needed

Post by RuadRauFlessa »

Use JDialog and make it modles and you are propably using JWindow to create the windows not JFrame as JFrame is a component which you can add to a JWindow. a JFrame itself will not show on the taskbar. But to resolve your problem use JDialog. The only other option would be JNDI which is a tad tricky and not always a wise choice as it becomes platform dependant.
:rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock:
Spoiler (show)
Intel Core i7-2600k @ 3.4GHz
Corsair Vengence 2x4GB DDR3 2000MHz
Thermaltake Toughpower 850W
ASUS nVidia GTX560 1GB
CoolerMaster HAF 932
User avatar
rustypup
Registered User
Posts: 8872
Joined: 13 Dec 2004, 02:00
Location: nullus pixius demonica
Contact:

Re: Java GUI application help needed

Post by rustypup »

JWindow with custom widgets will not appear in the taskbar...

DesktopPane/JInternalFrame is the way to go, but it sounds like your design may need some work... how many frames are you opening?
Most people would sooner die than think; in fact, they do so - Bertrand Russel
RuadRauFlessa
Registered User
Posts: 20576
Joined: 19 Sep 2003, 02:00
Location: Bloodbank

Re: Java GUI application help needed

Post by RuadRauFlessa »

The puppy is propably one up on me in terms of Java I have not worked with it for some thime thoug.

*Whips out manuals*
:rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock:
Spoiler (show)
Intel Core i7-2600k @ 3.4GHz
Corsair Vengence 2x4GB DDR3 2000MHz
Thermaltake Toughpower 850W
ASUS nVidia GTX560 1GB
CoolerMaster HAF 932
PypLaCe
Registered User
Posts: 214
Joined: 19 Apr 2005, 02:00
Location: Johannesburg
Contact:

Re: Java GUI application help needed

Post by PypLaCe »

Thanks! The jDialog does the trick. I didnt really try it as most of the articles that I read only made use of jDialogs as input type of forms where the user can input information on, and not windows which can act as "main" ones themselves.
User avatar
rustypup
Registered User
Posts: 8872
Joined: 13 Dec 2004, 02:00
Location: nullus pixius demonica
Contact:

Re: Java GUI application help needed

Post by rustypup »

PypLaCe wrote:most of the articles that I read only made use of jDialogs as input type of forms where the user can input information on, and not windows which can act as "main" ones themselves.
that would be because JDialog, as a container component, stinks around any decently threaded app... a modal dialog is even worse... i would strongly advise you use a properly threaded container, (JWindow), before using dialogs...
Most people would sooner die than think; in fact, they do so - Bertrand Russel
PypLaCe
Registered User
Posts: 214
Joined: 19 Apr 2005, 02:00
Location: Johannesburg
Contact:

Re: Java GUI application help needed

Post by PypLaCe »

@ rusty's earlier post

The application might have a process flow as follows:

On main screen, press button which displays search screen. On search screen, enter search key/text and hit button which displays search results screen and the results in jTable. On search results screen, select row in jTable and press button to show complete information on another screen.

This is just one of many that the app could have.

All these screens are jFrames at the moment.
RuadRauFlessa
Registered User
Posts: 20576
Joined: 19 Sep 2003, 02:00
Location: Bloodbank

Re: Java GUI application help needed

Post by RuadRauFlessa »

Events -- OOoh why people underestemate events I would never know

PypLaCe - events are your friends. Create your own event and pass the information you want or need displayed back with it. Then open up a new window and display the details. No need to have this huge chain of windows open. And I would have to agree with rusty regarding threads and JDialog. If you can avoid them like the plaige when using threads.

For event read this
:rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock:
Spoiler (show)
Intel Core i7-2600k @ 3.4GHz
Corsair Vengence 2x4GB DDR3 2000MHz
Thermaltake Toughpower 850W
ASUS nVidia GTX560 1GB
CoolerMaster HAF 932
RuadRauFlessa
Registered User
Posts: 20576
Joined: 19 Sep 2003, 02:00
Location: Bloodbank

Re: Java GUI application help needed

Post by RuadRauFlessa »

Any case I am quickly gonna grab the latest netbeans and have a look. I got some spare bw :D
:rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock:
Spoiler (show)
Intel Core i7-2600k @ 3.4GHz
Corsair Vengence 2x4GB DDR3 2000MHz
Thermaltake Toughpower 850W
ASUS nVidia GTX560 1GB
CoolerMaster HAF 932
PypLaCe
Registered User
Posts: 214
Joined: 19 Apr 2005, 02:00
Location: Johannesburg
Contact:

Re: Java GUI application help needed

Post by PypLaCe »

:lol: Im quite impressed with the latest netbeans... A lot better than what it was just a few year back.

Anyway, back to your previouse post RuadRauFlessa. That article on events that you linked to, isnt a bit overkill for what I want to do? I mean, I'm opening a few simple windows that display some info based on actions that took place in the previouse window. (Unless I'm not getting the picture you are trying to paint... :? )
RuadRauFlessa
Registered User
Posts: 20576
Joined: 19 Sep 2003, 02:00
Location: Bloodbank

Re: Java GUI application help needed

Post by RuadRauFlessa »

Well look at it this way

Main Screen -> Search Screen -> Search Display Screen -> Data Display Screen

See that as your flow of processes. Now by the time you (with your design) get to displaying the data to the user you will have 4 screens open. Instead cosnider the following

Main Screen -> Search Screen
-> Search Display Screen
-> Data Display Screen

Open the Search Screen and when it closes, using events, pass the search criteria back. Then open the Search Display Screen and pass it the search criteria which the search display screen will then use to retrieve the diffirent matches for the criteria. Then do the same for the Data Display Screen. Have the Search Display Screen only return the ID of the selected option (I assume the data you are searching for is indexed in a DB). Open the Data Display Screen and look up the data and display it. This is the most robust way you can handle screens. Yes you will have a bunch of callbacks in your main window but part of the idea is to complete abstraction.

You could always build all three screens into one but then you are going to rewrite a lot of code. with the above you only really need one search screen and then in the screen cater for any type of data you will need to search for. in the Search Display Screen you could make it dynamic enouth to be able to display search results for anything you are able to enter search criterion for in the Search Screen. The Data Display Screen you can do with what you want as you won't always want it dynamically generated. You could even set up some nice xml files to hold the defenitions for the diff screens or if you have a db store an entry for each thing you want to be able to search for.

The last version of NetBeans I worked on was 5.5. I have always been a fan of NetBeans. It used to be murder on resources but which IDE is not.
:rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock:
Spoiler (show)
Intel Core i7-2600k @ 3.4GHz
Corsair Vengence 2x4GB DDR3 2000MHz
Thermaltake Toughpower 850W
ASUS nVidia GTX560 1GB
CoolerMaster HAF 932
User avatar
rustypup
Registered User
Posts: 8872
Joined: 13 Dec 2004, 02:00
Location: nullus pixius demonica
Contact:

Re: Java GUI application help needed

Post by rustypup »

PypLaCe wrote:press button which displays search screen. On search screen, enter search key/text and hit button which displays search results screen and the results in jTable. On search results screen, select row in jTable and press button to show complete information on another screen.
ahh...

is there any reason the above transaction couldn't happen in one JInternalFrame... the "search" screen is effectively just requesting a single input field - no need to open multiple windows for each step in the operation...

JTable's MVC design means you can instantiate and use it before populating it with data - once you do populate it, the table will automatically alert any listeners, (table/scrollpane/viewport), to this fact and they, in turn, will automatically adjust layouts, cell renderers, etc to reflect the underlying change to the data...

the process, as you decribe it, would probably require that you would have an input panel to initiate the search process, a selectable tree panel to pick the relevant record and another panel to display the desired data, all of which could live, quite happily, within the same window...

<edit>
sorry - really busy at the moment.. will try and post some examples later..

to get you started:

Code: Select all

public class MyDataModel extends DefaultTableModel {
           private Vector<Vector<Object>> buf;
           private String[] headers = {"my","column","header","labels"};
           public MyDataModel(){
                     //init
           }
           //NB method
           public void setData(Vector<Vector<Object>> data){
                    buf = data;
                    this.fireTableDataChanged();//notify all listeners!
           }
           public int getColumnCount(){
                  return headers.length;
           }
           public int getRowCount(){
                  if(buf!=null)
                        return buf.size();
                  return 0;
           }
           public String getColumnName(int col){
                  return headers[col];
           }
           //example of how you can force a renderer type
           public Class getColumnClass(int col){
                  switch(col){
                           case 2:{return Boolean.class;} //will ensure a checkbox is used
                           default:{return String.class;}
                  }
           }
           public Object getValueAt(int row, int col){
                      if(buf!=null)
                          return buf.get(row).get(col);
           }
}

Code: Select all

public static void main(String[] args){
        javax.swing.JFrame frm = new javax.swing.JFrame("Table Model Test");
        frm.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);

        final MyDataModel mod = new MyDataModel();

        frm.add(new JScrollPane(new JTable(mod)));
        frm.setSize(640, 480);
        frm.setLocationRelativeTo(null);
        frm.setVisible(false);

        java.util.Timer tim = new java.util.Timer("TicTest");
        java.util.TimerTask tst = new java.util.TimerTask(){
                    public void run(){
                             Vector<Vector<Object>> data = new Vector<Vector<Object>>();
                              Vector<Object> row1 = new Vector<Object>();
                              Vector<Object> row2 = new Vector<Object>();
                              Vector<Object> row3 = new Vector<Object>();

                              row1.add("some");
                              row1.add("info");
                              row1.add(false);
                              row1.add("here");

                              row2.add("more");
                              row2.add("data");
                              row2.add(true);
                              row2.add("there");

                              row3.add("final");
                              row3.add("row");
                              row3.add(false);
                              row3.add("here");

                              data.add(row1);
                              data.add(row2);
                              data.add(row3);

                              mod.setData(data);//update the model
 
                     }
        };

        tim.schedule(tst, 120000);
}
apologies if it doesn't compile - i haven't tested this.. but it should give you some idea...
Most people would sooner die than think; in fact, they do so - Bertrand Russel
PypLaCe
Registered User
Posts: 214
Joined: 19 Apr 2005, 02:00
Location: Johannesburg
Contact:

Re: Java GUI application help needed

Post by PypLaCe »

(Sorry, havent refreshed the page in a while a didnt see your latest post... Reading it now)

There is no particular reason that they are on different windows other than that it separates the code...

So, by you saying that jDesktopPane/jInternal frame is the way to go, I assume that I should have the variouse windows merged into one jInternalFrame with variouse jPanels for each task? If that is the case (here is the noob question), how would i move between the variouse panels in the internal frame?
RuadRauFlessa
Registered User
Posts: 20576
Joined: 19 Sep 2003, 02:00
Location: Bloodbank

Re: Java GUI application help needed

Post by RuadRauFlessa »

Code: Select all

JFrame.remove([component]);
JFrame.add([component]);
:rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock: :rock:
Spoiler (show)
Intel Core i7-2600k @ 3.4GHz
Corsair Vengence 2x4GB DDR3 2000MHz
Thermaltake Toughpower 850W
ASUS nVidia GTX560 1GB
CoolerMaster HAF 932
User avatar
rustypup
Registered User
Posts: 8872
Joined: 13 Dec 2004, 02:00
Location: nullus pixius demonica
Contact:

Re: Java GUI application help needed

Post by rustypup »

ok... long post coming... expect it to be nasty... :lol:

If your package tree changes in any way, be sure to correct this in the class headers!

Package tree
=========
[src]
  • -simpledesktop
    • -factories
      • -DataSource.java
      -task
      • -DeferredTask.java
        -DeferredTaskEvent.java
        -DeferredTaskListener.java
        -TableCacheTask.java
        -TreeCacheTask.java
      -widgets
      • -ActionToggle.java
        -CustomTableModel.java
        -CustomTreeModel.java
        -ProcessPanel.java
        -SearchPane.java
      -DesktopExample.java
Under [factories]
==============
DataSource.java (dummy class used to spit out random information)
Spoiler (show)

Code: Select all

package simpledesktop.factories;

import java.util.ArrayList;

public class DataSource {
    public static int randomCap(int min, int max){
        int cap = (int)(Math.random()*(max*10));
        while(cap<min||cap>max)
            cap = (int)(Math.random()*(max*10));
        return cap;
    }
    public static String randomString(int cap){
        String retval = "";
        for(int x=0;x<cap;x++)
            retval+=DataSource.randomChar();
        return retval;
    }
    public static String randomString(){
        int cap = (int)(Math.random()*1000);
        while(cap>60)
            cap = (int)(Math.random()*1000);
        return DataSource.randomString(cap);
    }
    public static char randomChar(){
        int retval = (int)(Math.random()*244);
        while(retval<65||retval>122)
            retval = (int)(Math.random()*244);
        return (char)retval;
    }
    public static boolean randomBool(){
        return (((int)(Math.random()*100))&16)>0?true:false;
    }
    public static ArrayList<Object> makeRow(){
        ArrayList<Object> retval = new ArrayList<Object>();
        retval.add(DataSource.randomString());
        retval.add(DataSource.randomString());
        retval.add(DataSource.randomBool());
        retval.add(DataSource.randomString());
        retval.add(DataSource.randomChar());
        retval.add(DataSource.randomString());
        retval.add(DataSource.randomBool());
        
        return retval;
    }
    public static String[] makeHeaders(){
        String[] retval = {DataSource.randomString(7),DataSource.randomString(5),DataSource.randomString(6),DataSource.randomString(12),DataSource.randomString(3),DataSource.randomString(18),DataSource.randomString(4)};
        return retval;
    }
    public static ArrayList<ArrayList<Object>> makeDataSnap(){
        int cap = (int)(Math.random()*10000);
        while(cap<1000)
            cap = (int)(Math.random()*10000);
        ArrayList<ArrayList<Object>> retval = new ArrayList<ArrayList<Object>>();
        for(int x = 0;x<cap;x++)
            retval.add(DataSource.makeRow());
        return retval;
    }
}
Under [task]
==============
DeferredTask.java (Interface representing threaded tasks)
Spoiler (show)

Code: Select all

package simpledesktop.task;


public interface DeferredTask {
    public Object getResult();
    public void addDeferredTaskListener(DeferredTaskListener dtl);
    public void removeDeferredTaskListener(DeferredTaskListener dtl);
    public void updateListeners(DeferredTaskEvent dte);    
    public void terminate();
}
DeferredTaskEvent.java (The event object produced by a DeferredTask)
Spoiler (show)

Code: Select all

package simpledesktop.task;

public class DeferredTaskEvent {
    /**
     * Task status flags
     */
    public static enum DEFTASK_STATUS{
        /**
         * Task is newly initialised.
         */
        INIT,
        /**
         * Task is in a post-initialised state, ready to run.
         */
        PENDING,
        /**
         * Task is currently running.
         */
        RUNNING,
        /**
         * Task has changed.
         */
        UPDATE,
        /**
         * Task was paused.
         */
        PAUSED,
        /**
         * Task has resumed.
         */
        RESUMED,
        /**
         * Task has been completed.
         */
        DONE,
        /**
         * Task has experienced an error.
         */
        ERROR,
        /**
         * Task is in an indeterminant state.
         */
        UNKNOWN;
    }
    private DeferredTask srce;
    private Exception err;
    private DEFTASK_STATUS stat;
    
    public DeferredTaskEvent(DeferredTask source, DEFTASK_STATUS status){
        this(source, null, status);
    }
    public DeferredTaskEvent(DeferredTask source, Exception lastErr, DEFTASK_STATUS status){
        srce = source;
        err = lastErr;
        stat = status;
    }
    public DeferredTask getSource(){
        return srce;
    }
    public Exception getError(){
        return err;
    }
    public DEFTASK_STATUS getStatus(){
        return stat;
    }
}
DeferredTaskListener.java (Interface for classes which will process DeferredTask events)
Spoiler (show)

Code: Select all

package simpledesktop.task;

public interface DeferredTaskListener {
    public void taskUpdated(DeferredTaskEvent dte);
}
TableCacheTask.java (DeferredTask implementation concerned with producing table data)
Spoiler (show)

Code: Select all

package simpledesktop.task;

import java.util.ArrayList;
import java.util.TimerTask;
import simpledesktop.widgets.SearchPane;
import simpledesktop.factories.DataSource;

public class TableCacheTask extends TimerTask implements DeferredTask{
    private ArrayList<DeferredTaskListener> listeners;
    private ArrayList<ArrayList<Object>> result;
    private String qry;
    public TableCacheTask(String toSeek){
        SearchPane.PROCS.append(this, "Seek ["+toSeek+"]");
        SearchPane.PROCS.append(this, "Pending");
        this.updateListeners(new DeferredTaskEvent(this, DeferredTaskEvent.DEFTASK_STATUS.INIT));
    }
    public void run(){
        this.updateListeners(new DeferredTaskEvent(this, DeferredTaskEvent.DEFTASK_STATUS.RUNNING));
        SearchPane.PROCS.append(this, "Running");
        result = DataSource.makeDataSnap();
        SearchPane.PROCS.append(this, "Done");
        this.updateListeners(new DeferredTaskEvent(this, DeferredTaskEvent.DEFTASK_STATUS.DONE));
    }
    public Object getResult() {
        return result!=null?result:new ArrayList<ArrayList<Object>>();
    }
    public void addDeferredTaskListener(DeferredTaskListener dtl){
        //lazy listener stack instantiation
        if(dtl!=null&&listeners==null)
            listeners = new ArrayList<DeferredTaskListener>();
        if(dtl!=null)
            listeners.add(dtl);
    }
    public void removeDeferredTaskListener(DeferredTaskListener dtl) {
        if(dtl!=null&&listeners!=null&&listeners.size()>0)
            listeners.remove(dtl);
    }
    public void updateListeners(DeferredTaskEvent dte) {
        if(dte!=null&&listeners!=null&&listeners.size()>0){
            //ArrayLists are NOT thread safe!
            for(DeferredTaskListener dtl:listeners.toArray(new DeferredTaskListener[listeners.size()]))
                dtl.taskUpdated(dte);
        }
    }
    public void terminate(){
        super.cancel();
    }
}
TreeCacheTask.java (DeferredTask implementation concerned with producing tree data)
Spoiler (show)

Code: Select all

package simpledesktop.task;

import java.util.ArrayList;
import java.util.TimerTask;
import javax.swing.tree.DefaultMutableTreeNode;
import simpledesktop.widgets.SearchPane;
import simpledesktop.factories.DataSource;

public class TreeCacheTask extends TimerTask implements DeferredTask{
    private ArrayList<DeferredTaskListener> listeners;
    private DefaultMutableTreeNode result;
    private String qry;
    public TreeCacheTask(String toSeek){
        SearchPane.PROCS.append(this, "Seek ["+toSeek+"]");
        SearchPane.PROCS.append(this, "Pending");
        this.updateListeners(new DeferredTaskEvent(this, DeferredTaskEvent.DEFTASK_STATUS.INIT));
    }
    public void run(){
        this.updateListeners(new DeferredTaskEvent(this, DeferredTaskEvent.DEFTASK_STATUS.RUNNING));
        SearchPane.PROCS.append(this, "Running");
        //produce new tree structure
        result = new javax.swing.tree.DefaultMutableTreeNode("root",true);        
        for(int x = DataSource.randomCap(8, 24);x>0;x--){
            this.updateListeners(new DeferredTaskEvent(this, DeferredTaskEvent.DEFTASK_STATUS.UPDATE));
            SearchPane.PROCS.append(this, "["+x+"] Branches to go.");
            javax.swing.tree.DefaultMutableTreeNode sub = new javax.swing.tree.DefaultMutableTreeNode(DataSource.randomString(12), true);
            sub.add(new javax.swing.tree.DefaultMutableTreeNode(DataSource.randomString(7), false));
            SearchPane.PROCS.append(this, "Branch ["+sub.getUserObject()+"] buffered ["+sub.getFirstLeaf().getUserObject()+"].");
            result.add(sub);
        }
        SearchPane.PROCS.append(this, "Done");
        this.updateListeners(new DeferredTaskEvent(this, DeferredTaskEvent.DEFTASK_STATUS.DONE));
    }
    public Object getResult() {
        return result!=null?result:new DefaultMutableTreeNode("root");
    }
    public void addDeferredTaskListener(DeferredTaskListener dtl){
        //lazy listener stack instantiation
        if(dtl!=null&&listeners==null)
            listeners = new ArrayList<DeferredTaskListener>();
        if(dtl!=null)
            listeners.add(dtl);
    }
    public void removeDeferredTaskListener(DeferredTaskListener dtl) {
        if(dtl!=null&&listeners!=null&&listeners.size()>0)
            listeners.remove(dtl);
    }
    public void updateListeners(DeferredTaskEvent dte) {
        if(dte!=null&&listeners!=null&&listeners.size()>0){
            //ArrayLists are NOT thread safe!
            for(DeferredTaskListener dtl:listeners.toArray(new DeferredTaskListener[listeners.size()]))
                dtl.taskUpdated(dte);
        }
    }
    public void terminate(){
        super.cancel();
    }
}
Under [widgets]
==============
ActionToggle.java (Event listener used to process UI actions and generate cache tasks)
Spoiler (show)

Code: Select all

package simpledesktop.widgets;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Timer;
import java.util.ArrayList;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import simpledesktop.task.DeferredTaskEvent;
import simpledesktop.task.DeferredTaskListener;
import simpledesktop.task.TableCacheTask;
import simpledesktop.task.TreeCacheTask;

public class ActionToggle implements TreeSelectionListener, ActionListener, DeferredTaskListener{
    private CustomTableModel tab;
    private CustomTreeModel tree;
    private Timer tasks;
    public ActionToggle(CustomTableModel tableMod, CustomTreeModel treeMod){
        tab = tableMod;
        tree = treeMod;
        tasks = new Timer("Cache tasks");
    }

    public void valueChanged(TreeSelectionEvent e) {
        javax.swing.tree.DefaultMutableTreeNode node = (javax.swing.tree.DefaultMutableTreeNode)((javax.swing.JTree)e.getSource()).getLastSelectedPathComponent();
        if(node!=null&&!node.getAllowsChildren()){
            tab.setData(new ArrayList<ArrayList<Object>>());
            TableCacheTask tct = new TableCacheTask((String)node.getUserObject());
            tct.addDeferredTaskListener(this);
            tasks.schedule(tct, 10);
        }
    }
    public void actionPerformed(ActionEvent e) {
        TreeCacheTask tct = new TreeCacheTask(((javax.swing.JTextField)e.getSource()).getText());
        tct.addDeferredTaskListener(this);
        tasks.schedule(tct, 10);
    }
    public void taskUpdated(DeferredTaskEvent dte) {
        switch(dte.getStatus()){
            case DONE:{
                if(dte.getSource() instanceof TreeCacheTask)
                    tree.setTreeData((DefaultMutableTreeNode)dte.getSource().getResult());
                else
                    tab.setData((ArrayList<ArrayList<Object>>)dte.getSource().getResult());
                //clean up
                dte.getSource().removeDeferredTaskListener(this);
                dte.getSource().terminate();
                tasks.purge();
            }
        }
    }
}
CustomTableModel.java (Simple TableModel implementation)
Spoiler (show)

Code: Select all

package simpledesktop.widgets;

import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
import simpledesktop.factories.DataSource;

public class CustomTableModel extends AbstractTableModel{
    private ArrayList<ArrayList<Object>> buffer;
    private String[] heds = DataSource.makeHeaders();
    public CustomTableModel(){
        super();
    }
    public int getRowCount() {
        if(buffer!=null)
            return buffer.size();
        return 0;
    }
    public void setData(ArrayList<ArrayList<Object>> data){
        buffer = data;
        this.fireTableDataChanged();
    }
    public int getColumnCount() {
        return heds.length;        
    }
    public String getColumnName(int col){
        return heds[col];
    }
    public Class getColumnClass(int col){
        switch(col){
            case 2:{return Boolean.class;}
            case 6:{return Boolean.class;}
            default:{return String.class;}
        }
    }
    public Object getValueAt(int row, int col) {
        if(buffer!=null)
            return buffer.get(row).get(col);
        return null;
    }
    
}
CustomTreeModel.java (Silly TreeModel implementation)
Spoiler (show)

Code: Select all

package simpledesktop.widgets;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

public class CustomTreeModel extends DefaultTreeModel{
    public CustomTreeModel(){
        super(new DefaultMutableTreeNode("root"));
    }
    /*
     * Mimic root seek event - overridden purely because earlier
     * JVMs had some trouble with the setRoot() method not triggering the change
     * event.
     */
    public void setTreeData(DefaultMutableTreeNode newRoot){
        super.setRoot(newRoot);
    }
}
ProcessPanel.java (Spits out various event info - just used to show tabbed pane operation)
Spoiler (show)

Code: Select all

package simpledesktop.widgets;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import javax.swing.JTextArea;

public class ProcessPanel extends JTextArea{
    
    private DateFormat DF = new SimpleDateFormat("[yyyy-MM-dd] {kk:mm:ss.S}:");
    public ProcessPanel(){
        super();
        super.setEditable(false);
        super.setOpaque(true);
        super.setForeground(java.awt.Color.WHITE);
        super.setBackground(java.awt.Color.DARK_GRAY);
    }
    public void append(Object srce, String x){
        super.insert(DF.format(new java.util.Date())+ "[" + srce.getClass().getSimpleName() + "] -- " + x+"\r\n", super.getText().length());
        super.setCaretPosition(super.getText().length());
    }
}
SearchPane.java (The main UI view of the process, bringing the various panels together and registering event listeners)
Spoiler (show)

Code: Select all

package simpledesktop.widgets;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JTree;

public class SearchPane extends JPanel implements FocusListener, ActionListener{
    public static ProcessPanel PROCS = new ProcessPanel();
    private JTextField input;
    private CustomTableModel tab;
    private CustomTreeModel tree;
    private ActionToggle toggle;
    
    public SearchPane(){
        super(new BorderLayout());
        
        tab = new CustomTableModel();
        tree = new CustomTreeModel();
        toggle = new ActionToggle(tab,tree);
        
        JPanel inpt = new JPanel(new BorderLayout(2,2));
        input = new JTextField("<search term here>");
        input.addActionListener(toggle);
        input.addActionListener(this);
        input.addFocusListener(this);
        
        inpt.add(new JLabel("  SEARCH  "), BorderLayout.WEST);
        inpt.add(input, BorderLayout.CENTER);
        
        JTree t = new JTree(tree);
        t.addTreeSelectionListener(toggle);
        t.setRootVisible(false);
        t.setPreferredSize(new java.awt.Dimension(120, 480));
        
        JSplitPane split = new JSplitPane();
        split.setDividerLocation(0.6);
        
        split.add(new JScrollPane(t), JSplitPane.LEFT);
        split.add(new JScrollPane(new JTable(tab)), JSplitPane.RIGHT);
        
        
        JTabbedPane tabs = new JTabbedPane();
        tabs.add("Search Pane", split);
        tabs.add("Output", new JScrollPane(SearchPane.PROCS));
        
        super.add(tabs, BorderLayout.CENTER);
        super.add(inpt, BorderLayout.SOUTH);
    }
    public void focusGained(FocusEvent e) {
        input.selectAll();
    }
    public void focusLost(FocusEvent e) {}
    public void actionPerformed(ActionEvent e) {
        input.selectAll();
    }
}
Under [simpledesktop]
==============
DesktopExample.java (Main dekstop UI, showing how to manage menus, internal frames, etc)
Spoiler (show)

Code: Select all

package simpledesktop;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyVetoException;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
import simpledesktop.widgets.SearchPane;

public class DesktopExample extends JFrame implements ActionListener, InternalFrameListener{
    private JMenuItem term, init;
    private JDesktopPane desktop;
    public DesktopExample(){
        super("JDesktop Example");
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        desktop = new JDesktopPane();
        JMenuBar bar = new JMenuBar();
        
        term = new JMenuItem(" Exit ");
        term.addActionListener(this);
        term.setActionCommand("exit");
        init = new JMenuItem(" Search ");
        init.addActionListener(this);
        
        bar.add(term);
        bar.add(init);
        
        super.setJMenuBar(bar);
        
        super.setSize(640, 480);
        super.setLocationRelativeTo(null);
        super.add(desktop);
        super.setVisible(true);
    }
    public void internalFrameOpened(InternalFrameEvent e){}

    public void internalFrameClosing(InternalFrameEvent e){
        
    }

    public void internalFrameClosed(InternalFrameEvent e){
        e.getInternalFrame().removeInternalFrameListener(this);
        init.setEnabled(true);
    }

    public void internalFrameIconified(InternalFrameEvent e){}

    public void internalFrameDeiconified(InternalFrameEvent e){}

    public void internalFrameActivated(InternalFrameEvent e){}

    public void internalFrameDeactivated(InternalFrameEvent e){}
    
    public void actionPerformed(ActionEvent ae){
        if(ae.getSource() instanceof JMenuItem){
            if(ae.getActionCommand().equals("exit"))
                System.exit(0);
            else{
                JInternalFrame frm = new JInternalFrame("Search Tool Example", true, true, true, true);
                frm.setSize(640, 480);
                frm.addInternalFrameListener(this);
                frm.getContentPane().add(new SearchPane(), java.awt.BorderLayout.CENTER);
                
                init.setEnabled(false);
                
                desktop.add(frm, JDesktopPane.DEFAULT_LAYER, -1);
                
                frm.toFront();
                try
                {
                    frm.setSelected(true);
                    frm.setVisible(true);
                    frm.setMaximum(true);
                }
                catch(PropertyVetoException pve)
                {
                    pve.printStackTrace();
                }   
            }
        }
    }
    public static void main(String[] args){
       DesktopExample de = new DesktopExample();
    }
}
Last edited by rustypup on 15 Jan 2009, 10:48, edited 1 time in total.
Most people would sooner die than think; in fact, they do so - Bertrand Russel
User avatar
rustypup
Registered User
Posts: 8872
Joined: 13 Dec 2004, 02:00
Location: nullus pixius demonica
Contact:

Re: Java GUI application help needed

Post by rustypup »

once you've got it to compile, we'll chat again.. :)

<edit>
perfect spacing - see prior page...
</edit>
Most people would sooner die than think; in fact, they do so - Bertrand Russel
Post Reply