Discussions
Categories
- 196.9K All Categories
- 2.2K Data
- 239 Big Data Appliance
- 1.9K Data Science
- 450.3K Databases
- 221.7K General Database Discussions
- 3.8K Java and JavaScript in the Database
- 31 Multilingual Engine
- 550 MySQL Community Space
- 478 NoSQL Database
- 7.9K Oracle Database Express Edition (XE)
- 3K ORDS, SODA & JSON in the Database
- 546 SQLcl
- 4K SQL Developer Data Modeler
- 187K SQL & PL/SQL
- 21.3K SQL Developer
- 295.9K Development
- 17 Developer Projects
- 138 Programming Languages
- 292.6K Development Tools
- 107 DevOps
- 3.1K QA/Testing
- 646K Java
- 28 Java Learning Subscription
- 37K Database Connectivity
- 155 Java Community Process
- 105 Java 25
- 22.1K Java APIs
- 138.1K Java Development Tools
- 165.3K Java EE (Java Enterprise Edition)
- 18 Java Essentials
- 160 Java 8 Questions
- 86K Java Programming
- 80 Java Puzzle Ball
- 65.1K New To Java
- 1.7K Training / Learning / Certification
- 13.8K Java HotSpot Virtual Machine
- 94.3K Java SE
- 13.8K Java Security
- 204 Java User Groups
- 24 JavaScript - Nashorn
- Programs
- 442 LiveLabs
- 38 Workshops
- 10.2K Software
- 6.7K Berkeley DB Family
- 3.5K JHeadstart
- 5.7K Other Languages
- 2.3K Chinese
- 171 Deutsche Oracle Community
- 1.1K Español
- 1.9K Japanese
- 232 Portuguese
adding log as a scrolling JList within aJDialog
I am designing the final item for the Help menu of the [url http://r0k.us/graphics/SIHwheel.html]Interactive Color Wheel. It will be a log of user actions, to replace and extend the System.out.println() info currently going to the Java Console.
Preliminary Design
1) implemented as a single-instance JDialog containing a scrolling JList
2) typically 2 rows per entry. background color for both rows equal to selected color
3) potential 3rd row if color name mismatch (a limitation of quantized color space)
4) potential 4th row when user has Quantization Error toggled on
5) created invisibly. records events whether visible or not
The 4 rows would look something like:
Concerns
1) Is there a practical or actual limit to how many items in JList?
2) Whether or not limit, would it be beneficial to discard earliest rows when beyond some pre-determined limit?
3) Is there an easy way to enable copying JList rows (or dragged text) to clipboard?
.... If not, I'll add button to enable copying selected row(s) to clipboard.
4) Is a scrolling JList actually the best way to handle all this?
The clipboard stuff is based on user feedback. Some folks are looking for specific color(s), and they would like an easy way to capture that info.
Any feedback about my concerns, or even the general design, would be appreciated. Thank you.
-- Rich
Preliminary Design
1) implemented as a single-instance JDialog containing a scrolling JList
2) typically 2 rows per entry. background color for both rows equal to selected color
3) potential 3rd row if color name mismatch (a limitation of quantized color space)
4) potential 4th row when user has Quantization Error toggled on
5) created invisibly. records events whether visible or not
The 4 rows would look something like:
@Frangipani -- #ffd9b3, luma = 217, complement = #b3d9ff r,g,b = 255, 217, 179 -- h,s,b = 30°, 29.8%, 255 Frangipani (FFDEB3) != NTC's Light Apricot (#FDD5B1), false hqe(#FDD5B1) = (2r, 4g, 2b) = 3%Normally, only the first two lines would exist. The third and/or fourth lines are conditional.
Concerns
1) Is there a practical or actual limit to how many items in JList?
2) Whether or not limit, would it be beneficial to discard earliest rows when beyond some pre-determined limit?
3) Is there an easy way to enable copying JList rows (or dragged text) to clipboard?
.... If not, I'll add button to enable copying selected row(s) to clipboard.
4) Is a scrolling JList actually the best way to handle all this?
The clipboard stuff is based on user feedback. Some folks are looking for specific color(s), and they would like an easy way to capture that info.
Any feedback about my concerns, or even the general design, would be appreciated. Thank you.
-- Rich
Tagged:
Answers
-
How about using a JTable.
You create a custom Object to store all the information, then you can display this information in the columns of the table.
Its easy to control the number of rows in the table if you wish.
A table already supports copying a row to the cliipboard.
Or maybe a JTree. The main node would represent the log entry. Then multiple child nodes would represent the details. Not sure how copying to the clipboard would work.
The key to each of these is that each object is represented at a high level so its easy to idenify and remove a complete object. Using the JList approach you don't know if you have 2, 3, 4 lines of data for each object. -
Nevermind, found the problem. See next post.
I probably will go with the JTable approach. I was concerned about width, but then it occurred to me that all the columns need not be full width; most users will not be interested in the optional info anyways.
But right now I am fighting a weird "two windows with one handle" problem. I've stripped my program down to a stand-alone executable that demonstrates the problem:import java.awt.*; import java.awt.event.*; import javax.swing.*; public class LogBox extends JApplet { public static SIHListPane colorList; public static HelpBox lBox; public void init() { // the static block above should have already executed try { javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { JPanel frame = makeContent(); setContentPane(frame); } }); } catch (Exception e) { System.err.println("makeContent() failed to complete: " + e); e.printStackTrace(); } } public JPanel makeContent() { colorList = new SIHListPane(); lBox = new HelpBox("Log", new Dimension(800, 400)); JPanel outer = new JPanel(); outer.add(colorList); return(outer); } // method expected by programs public static void main(String args[]) { // JFrame exists only when running as program, not applet SwingUtilities.invokeLater(new Runnable() { // something to do with concurrency ... // @Override // not supported in target Java 4 platform public void run() { // the static block at top should have initialized NTC already JFrame f = new JFrame("LogBox Test"); LogBox logBox = new LogBox(); // in this paradigm, main() does not call init() f.setContentPane(logBox.makeContent()); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setResizable(false); f.pack(); f.setLocationRelativeTo(null); // center on screen f.setVisible(true); } }); } } // list-widget GUI class SIHListPane extends JPanel { private JTextField hexEntry; private String normalHexLabel = new String("Hex Color: "); private JLabel hexLabel = new JLabel(normalHexLabel); public SIHListPane() { this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); JMenuBar menuBar = new JMenuBar(); menuBar.setBorderPainted(true); menuBar.setPreferredSize(new Dimension(200, 40)); JMenu dictionary = new JMenu("Color Lists"); menuBar.add(dictionary); menuBar.add(Box.createHorizontalGlue()); JMenu help = new JMenu("Help"); JMenuItem log = new JMenuItem("Show Log"); log.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { LogBox.lBox.setVisible(true); } }); help.add(log); menuBar.add(help); add(menuBar); JPanel hexPanel = new JPanel(); hexPanel.setBorder(BorderFactory.createLineBorder(Color.black, 1)); hexPanel.setPreferredSize(new Dimension(200, 30)); hexPanel.add(hexLabel); hexEntry = new JTextField("", 6); hexEntry.setForeground(Color.white); hexEntry.setBackground(Color.darkGray); hexEntry.setCaretColor(Color.lightGray); hexEntry.setToolTipText("3-digit CSS or 6-digit HTML"); hexEntry.setActionCommand("hText"); hexPanel.add(hexEntry); add(hexPanel); } } class HelpBox extends JDialog { private JDialog jd; // window for log; instantiated once, in a runnable of SIHwheel HelpBox(String title, Dimension size) { jd = new JDialog((Frame)null, title, false); jd.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); jd.setPreferredSize(size); jd.pack(); jd.setLocationRelativeTo(null); jd.setVisible(true); } }
I know it appears very convoluted, but I kept the structure of the 3454-line SIHwheel.java source. It seemed a good idea to keep the full environment in the test.
The initial problem was that the JDialog shows from the menu uncentered, with no title and no size. As a debug step, I added the final "jd.setVisible(true);" line you see several centimeters above. Thus the dialog shows when you launch the program, and it has location, size, and title. Use the help menu to display it, and a second dialog appears, but again in ULC with no title or size. There are two dialogs!
What is even weirder, is that they have the same handle. Obscure or partially obscure both, then use menu to make "it" visible". They both come to the front!
If you make the titled dialog go away, you cannot get it back. There is only the untitled one left. You can make it go away and come back as many times as you want, and it remembers where you moved it to and how you resized it.
If you got this far, you are probably wondering why the dialog is created in a separate class. The HelpBox class is actually bigger than I show. and will be handling creation and management of the JTable pane which will go into the dialog. It also has a second (actually first) constructor, to create an HTML help window. The creation of that dialog is handled within an embedded runnable. I didn't feel that the log window needed to be created directly within a runnable because it is launched from a runnable up top.
I just tried extending the test program above to use a runnable in the creation of the log window, and it made no difference.HelpBox(String pTitle, Dimension pSize) { final String title = pTitle; final Dimension size = pSize; SwingUtilities.invokeLater(new Runnable() { public void run() { jd = new JDialog((Frame)null, title, false); jd.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); jd.setPreferredSize(size); jd.pack(); jd.setLocationRelativeTo(null); jd.setVisible(true); } }); }
The permanent log window made visible by the menu still has no title or size. The initial one displayed has these characteristics. And they both still respond to the menu setVisible() command.
Edited by: RichF on Nov 28, 2010 8:41 AM -
I just extended the constructor to include adding a JTable. My hope was that if it had something inside of it, the dialog would behave itself. Nope.
<<< moot >>>
The initial, temporary one has everything, including the JTable. The permanent one is still completely empty, sizeless, and titleless.
Edited by: RichF on Nov 28, 2010 8:42 AM
Found the darn problem! An apple is not an orange.----- in the menu constructor ----- JMenu help = new JMenu("Help"); JMenuItem log = new JMenuItem("Show Log"); log.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { LogBox.lBox.getDialog().setVisible(true); } }); ----- the HelpBox class ----- class HelpBox extends JDialog { private JDialog jd; // window for log; instantiated once, in a runnable of SIHwheel HelpBox(String title, Dimension size) { jd = new JDialog((Frame)null, title, false); jd.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); jd.setPreferredSize(size); jd.pack(); jd.setLocationRelativeTo(null); JTable jt = new JTable(10, 8); jd.getContentPane().add(jt); } public JDialog getDialog() { return(jd); } }
Sorry to waste your time. -
Better yet, I stopped using jd altogether. The first line of the constructor is now:
super((Frame)null, title, false);
The menu callback has gone back to its original form, without the getDialog() segment.
I didn't do this initially because it wouldn't work in the first constructor.// general window for display of HTML page HelpBox(String pTitle, String pUrlS, boolean pModal, Dimension pSize) { final String title = pTitle; final String urlS = pUrlS; final Dimension size = pSize; final boolean modal = pModal; SwingUtilities.invokeLater(new Runnable() { public void run() { jd = new JDialog((Frame)null, title, modal); jd.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); JEditorPane ep = new JEditorPane(); ep.setEditable(false); try { URL url = getClass().getResource(urlS); ep.setPage(url); JScrollPane eps = new JScrollPane(ep); eps.setPreferredSize(size); jd.getContentPane().add(eps, BorderLayout.CENTER); } catch (IOException ioE) { System.err.println("Unable to display help pane"); ioE.printStackTrace(); } jd.pack(); jd.setLocationRelativeTo(null); jd.setVisible(true); } }); }
I could not find any way to stick a super() constructor in there that would let me also have a runnable. With a first constructor line ofsuper((Frame)null, pTitle, pModal);
, how the heck do you reference that from the runnable doohickey below? The runnable compiles separately, "HelpBox$1.class".
(a few minutes later). Nevermind. You don't reference it. Somehow it knows that a simple pack() within the runnable class means the thing created outside the runnable, in the super() constructor of the primary HelpBox class.
Note to Rich: stop overthinking things. Try simple first. -
camickr wrote:I've started work on the JTable infrastructure. I cannot find a method to add (or delete) a row in either the [url http://download.oracle.com/javase/1.4.2/docs/api/javax/swing/JTable.html]JTable docs or the [url http://download.oracle.com/javase/7/docs/api/javax/swing/table/TableModel.html]TableModel docs. The [url http://download.oracle.com/javase/tutorial/uiswing/components/table.html]tutorial does not mention it either. I'm likely missing something obvious, but what?
How about using a JTable.
...
Its easy to control the number of rows in the table if you wish.
Curiously, there is an addColumn() method, but not an addRow(). -
-
I cannot find a method to add (or delete) a row in either the JTable docs or the TableModel docs.No this is not a method of the TableModel interface.
However, add/removeRow methods are implemented on the DefaultTableModel. Or if you need a create a customized TableModel to hold your logging Object then you can try using the [url http://tips4java.wordpress.com/2008/11/27/bean-table-model/]Bean Table Model -
There I go, thinking again. TableModel is obviously more flexible than DefaultTableModel, right?
( answer: no! )
-
I have the first pass up and running at my site:
* http://r0k.us/graphics/SIHwheel.html
The JTable is part of the Color Log, accessed via the Help --> Show Log menu item. It uses the DefaultTableModel unchanged. Even as is, it provides significantly more capability than the previous logging to System.out. And I don't have to explain to anyone how to access the Java Console!
There are still some things I plan to do:
1) gain access to the system clipboard so that the user can copy data there. Apparently I'll have to sign the applet and likely pay some 3rd party verifier to prevent a "do you really want to run this" requester whenever someone accesses the page. Sigh, I don't make any money from this, so paying someone just to allow copying to the clipboard seems pretty darn extravagant. (How come users can copy from the HTML page to the clipboard, but not from a Java applet on that page? I know there is a sandbox, but what would be the harm in access to the clipboard? You can even copy stuff from the Java Console for the applet! Only the poor applet itself is naked and alone.)
2) Add a custom renderer so I can display rows in the various colors being logged.
3) Pretty-up general formatting -- column widths, data alignment, etc.
4) Probably begin auto-deleting early rows. I'm thinking whenever row count gets to 3500, delete the first 1000 rows. Is this a good idea?
5) Probably eliminate cell-editing. The capability doesn't seem to be hurting anything, but it seems to interfere with row selection and <ctrl>c copies to the clipboard. (Tested when running as a program, not an applet.)
6) I'd like the row(s) selection and copy feature of a default JTable, with no table model specified. That's actually on the back-burner until I decide whether to start signing and having it verified.
I'll appreciate suggestions concerning presentation and/or implementation. Thanks.
-- Rich -
!!???!! One can copy to the clipboard either of the JTextField's, or any of the table cells. However, the button on the color log, which saves all the data below it, casts a security violation when executed as an applet. How can I bypass the violation and do the same thing those widgets are allowed to do?
This discussion has been closed.