Java Swing Threading Problem - java

so here's the problem. I have a JDialog box that consists of 3 combo boxes, a text field, a few buttons and a JTable. The JTable information is filtered based on the text field and combo boxes, so for instance it starts with all of the data and gets shrunk down to only the data that starts with any string value the user decides.
What's happening though is that while the values filter correctly, if I click in the JTable (in the white space, where there are no rows) then the rows that were deleted show up, like they were invisible until I clicked on them. I've tried almost everything:
I've tried re-creating the table every time filter is clicked (bad hack that didn't even work), I've called all of the repaint, revalidate, firechanged methods, I rewrote the dialog from scratch to make sure I didn't do any stupid mistakes (if I made one I didn't find it at least), and I've tried putting them on separate threads. The only fix I haven't tried is using a swing worker, but that's because my filtering was a little too complicated for me to figure out what goes where and how to extend the swing worker correctly. The GUI is generated by netbeans (bleh), and has worked in my other dozen or so JDialogs just fine (perfectly in fact). Here's the method that doest the filtering, if any of you can help it would be greatly appreciated.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
nameFilter = "task1";
javax.swing.table.DefaultTableModel dm = (javax.swing.table.DefaultTableModel)jTable1.getModel();
tempParameters = parameters;
String currentString;
int rowNumber = 0;
while (dm.getRowCount()>rowNumber){
currentString = (String)(jTable1.getValueAt(rowNumber,1));
if(!nameFilter.equalsIgnoreCase(currentString.substring(0,nameFilter.length()))){
dm.removeRow(rowNumber);
parameters--;
}
else rowNumber++;
}
parameters = numOfRows;
}
Update, I also implemented the filter from the comment below, and while it filtered out the correct data, it had the exact same problem. In the future I will probably use this filter feature though, so thanks.
Another update, the code is still failing even after removing everything but this chunk, and all (at least I believe..) I am doing here is doing a simple remove row call. Hope this helps a bit.

Have you tried creating a new Model every time you want to filter, instead of clearing it by deleting rows? Create new model, copy relevant rows to new Model, set new Model in table. Really shouldn't be necessary, but it might be a quick fix.
Also, I really have to wonder why you're calling toLowerCase on two strings when you're using equalsIgnoreCase to compare them.

So long as this method is called from the EDT I don't think there would be a threading problem. Try using
SwingUtilties.isEventDispatchThread()
to make sure.
If you look at the API for DefaultTableModel, updates are being sent to your JTable which will repaint itself, so I don't think that is the problem.
I would guess that it is a logic problem. If you can extract the logic into separate methods it will be easier to test and verify whether it is updating the model as you expect.

Couple of observations:
If the filter happens to be larger than the string content of the row, it'll throw in the substring call
Calling the dm.removerow is generating a bunch of tablerowsdeleted events.
You're asking for a rowcount from the model, yet are getting the value through the table (a little inconsistent, if the model gets wrapped around another model you might be acting upon different rows), so instead of jtable1.getvalueat, use the dm.getvalueat.
I think what might be happening is that as the events get fired I see there are repaint and revalidate events fired in the JTable, these can be trampling over each other as they get enqueued in the EDT.
What I would suggest is to create a new datamodel, add the rows that you want to keep, and then reassign it to your jTable1.setModel(newDm);
Also to watch for is if someone else is modifying the model while you're in your eventlistener.
Hope this helps

Related

Concurrency problem in updating Jtable/Jframes?

I will try to describe the problem as accurately as possible, since this is a legacy project from someone else that I am trying to fix (to the best of my abilities).I cannot build an accurate working example due to the way this project is done. The way this program was built is wrong in many places so just pinpointing the problem would help me immensely.
There is a Jframe with a menu bar and table. The frame switches between Tables based on which option you click within the menu bar. Here's the problem: When updating the table, the first table seems to be fine, but the other ones fails to update its view properly if something is changed (specifically, it doesn't update upon deletion, but insertion seems fine). This is how the main table is made:
public void start(){
mainTable=new Jtable(model){
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
/* tons of styling here */
};
}
/* a bit more styling? */
renderSecondTable();
renderThirdTable();
}
I apologize for this ugly code, the codebase itself is even worse. Does rendering other tables by calling a method within this "start()" function lead to concurrency problems? Which is why updating the view is problematic? Extra information that might help:
each table has a seperate Frame, so there is a main frame and then a smaller frame that displays the tables
buttons for each table (delete, update etc.) are also added in by calling in extra methods like RenderButtonsForTable1()
They are all AbstractTableModel
calling FireTableDataChanged() or other similar functions do not seem to do work for non-main-tables
revalidate and repaint also doesn't work
The table does NOT use removeRow or fireTableRowsDeleted to remove the rows, there are seperate functions that do this with object streams (I don't quite understand this yet). The view seems to update automatically for the main table just fine.
Again I apologize if this is extremely confusing and ugly, the original creator didn't seem to understand what he was doing either :/
Edit: More clarification!
It seems that it does in fact only have one MAIN frame, and this
frame swaps out multiple Jpanels (each with a different Table). Within each Panel there is also a scrollpane
Deleting from the main Panel causes no problems, but deleting entries from other Panels require the Frame to be reopened or else the entry just stays there (also breaks the frame/panel completely if you empty the entire table)
The entry is properly disposed of in the backend (as far as I can tell)
any insert/delete is done through an action listener for the corresponding button
Each table has a seperate Tablemodel (all extends AbstractTableModel) with its seperate functions that all do the same thing
Table is filled with data read from a database
all tables are made in the same fashion as the main one above with prepareRenderer
I also drew up a vague diagram of how the Jframe looks:

How to update a panel which shows details of an object

I have a panel, let's call it detailsPanel, which holds a Person reference and displays its field values in the following manner:
Name: person.getName ();
Surname: person.getSurname ();
Emain: person.getEmail ();
.... .......
.... .......
And so on. I will use JLabels (correctly aligned using a GridBagLayout) to show each (fieldName, fieldValue). I have a lot of fields to display.
The problem is that the panel which shows the details must be always visible, i.e it will not be shown in a modal JDialog, so that i could create the panel by simply reading my Person object fields at the panel creation.
The panel must always be visible, and its Person reference will change when the user selects a different row in a Person list. This means i will call a method to update its state, something like:
detailsPanel.setPerson (aPerson);
Now, i'm wondering how i should update all the fields. Should i keep a reference to all the JLabels which show the values, and use setText(value) on each of them when i update the panel, or would it be better to override getText() method for every label, returning the correct field value, so that in the update method i would only repaint the panel, and the text would automatically change when the getter method is used on a different Person object?
Any suggestion is appreciated!
Since this is UI stuff which is usually called almost never (relative to how often things are called in other computation) you don't need to worry about efficiency at all. Just do what you think is the most elegant solution. There are three options That quickly come to my mind. They are ordered from quick and static to elegant and reusable:
Quick and dirty: create your constructor and make everything look nice. Then move everything from the constructor to a separate init() method and every time the entities change, you just call removeAll(); and then init() again.
As you suggested, keep a reference to all labels and use the setPerson() method to update all panels. Then call this method in the constructor (this is arguably the most common solution).
As you suggested, build your own extension of JLabel. This new class should either have an update() method which is to be called when things change, or have it set its own listeners to ensure that it gets notified of any relevant change.
If you are planning to create a single panel which is supposed to display all kinds of objects, you could have those object implement an interface called Displayable which gives you generic access to all its values and maybe even listeners to each value. An alternative to the Displayable interface is to use reflection and use annotations to allow the panel to get its values for display.
Please note that the most elegant solution is - contrary to what some people may tell you - not always the best for any situation. How much maintenance do you expect there to be in the future? How big is the application? Will you ever hand off the code to someone else? All these and more need to be considered to decide how "nice" you want your solution to be.

Any way to delay PaintComponent?

I've read through lots of the threads on paintComponent here, most of which making the point that it either is never or almost never necessary (or possible) to choose when paintComponent is called.
In my program, however, sometimes (only sometimes) paintComponent gets called before some of the objects it needs to paint have finished initializing or even sometimes before they've been created, triggering warnings- JOptionPane pop-ups, which surprisingly do not show any of the text they were hard-coded to display in their "message" area. I've read in other places that it's something to do with the EDT, and I've looked into some parts of that but I'm just getting confused. If the main purpose of the EDT is to update the gui, and by default pretty much everything will run in the EDT, then could I tell the program to run all the initialization and update functions in a different thread(s), which I somehow forcibly make run before the EDT runs?
What I'd ideally like to have happen is for paintComponent to wait until a certain point in my code to be run (after a bunch of update functions, regardless of what happens to the screen. After it does get called, it is followed by a pause in which relatively little is going on ( I had been using Thread.sleep() inside a while loop ) and which lasts until the user clicks something - at which point all the necessary functions are run again, followed by paintComponent afterwards, then the sleep() while loop, etc.
From what I understand, I think what I want isn't really possible, so my question is: Do you guys have any ideas of how to get around this?
EDIT:
So essentially the program is a college course planner, intended to make it easier for someone to plan out by semester all the courses they have to take before graduation, move those courses around (if possible), and see how all the courses are connected (prerequisites and such). When the program starts, it loads the list of necessary courses from a text file, then loads info about each course from a bunch of individual text files, and arranges them according to their prerequisites. Courses with no prerequisites go in the first semester, courses whose prerequisites have all been added to the first semester get added to the second, and so on until all the courses have been added. When paintComponent runs, it calls a function that assume all of each course's prerequisites exist on the schedule, and if it finds otherwise, it throws an error and displays a JOptionPane message box. When this happens during a normal run of the program (like if I manually add a course before adding its prerequisites), that all works and displays correctly. But sometimes that message box pops up when only some of the courses have been loaded (meaning control is still in the main constructor) and when it does so, the actual string message doesn't show up - only the actual pane, title and ok button do. Heres the line where I display the error box, so you can know that I'm not trying to display a string variable which has the potential of being empty.
JOptionPane.showMessageDialog(this,
"Course couldn't be loaded, partially >loaded\ncourses have been removed.",
"Error",
JOptionPane.OK_OPTION);
It is the "Course couldn't...been removed." part that doesn't get displayed. This is the only JOptionPane I display with the title "Error".
This post mentioned what sounds like the same thing happening, except I'm not using any of the things that poster had to fix. So possibly it's irrelevant but I'll add it just in case. JOptionPane.showMessageDialog() shows but without any message?
But to step back a bit, because that box popped up before all the courses had been added, it means that paintComponent was somehow called in the middle of the relevant JPanel's constructor, before a bunch of things had been initialized. I added a bunch of println() statements to make sure that that is true. Is it normal for that to happen, and if so, is there a way to fix it without simply using Andrew Thompson's advice?
After thinking though it a bit, I think that because the project is 3200 lines long and relies to a huge extent on text files, I'm really not sure how to ( or if I can) make a SSCCE for it..
If any specific pieces would be helpful I'll gladly add those but if this problem isn't clearly some standard issue I'm getting wrong, then I'll just add that flag and keep looking for bugs.
Thanks for your help
Declare a flag as a class attribute. Check it in the paint method. Change it at the end of the initialization.
class XandYandZ extends JComponent {
boolean initializationFinished = false;
public XandYandZ() {
// long initialisation..
initializationFinished = true;
}
public void paintComponent(Graphics g) {
if (!initializationFinished) return;
// .. paint ..

How to make two documents update each other during real time depending on each other input?

Supposedly there are two abstract documents that correspond to JTextFields (Both JTextFields are different variables).
Suppose, user inputs numeric value in JtextField1(document A), it should update the other JTextField2(document B) during run time accordingly. The same goes if user inputs numeric value in JTextField2(Document B) at the same program run time, it should update JTextField1(Document A).
I tried solving this by using Document Listener, however, it will work only on updating one document(either A updates B or vice versa) during run time rather than both (or each other to be precise) as it provides a deadlock. Should I use DocumentFilter for this problem? I am clueless how I would apply it for this situation, though. I tried avoiding deadlock/write lock problem by using FocusListeners and disabling DocumentListener when the field is not in focus, but it was a very naive approach as it totally does not deal with threads(if that is the problem). Would creating a separate thread when the other field is selected suffice?I have no real knowledge in multi threading, though. I would appreciate a some sort of advice on this problem.
code: http://pastebin.com/qqYPXcAf
I m trying to recreate similar GUI functionality of photoshop that updates width/height size in pixels for keeping AR during run time on user input (picture: http://puu.sh/9L07v/c745e85867.png)
Should I use DocumentFilter for this problem?
An easier solution is to just share the Document:
JTextField textField1 = new JTextField(...);
JTextField textField2 = new JTextField(...);
textField2.setDocument( textField1.getDocument() );
Or if you code is doing some kind of calculation so that the two values are different then you can just remove the DocumentListener to avoid looping. So the basic code for the listener on textField2 would be:
textField1.getDocument().removeDocumentListener(...);
textField1.setText( ... );
textField1.addDocumentListener(...);
So know when you update the text in text field one it will not notify textField2.

GWT 2 ButtonCell in one row Adding Event

could someone help me. I'm new to gwt and maybe this is so simple. but I can't seem to figure this out...
I create 2 button for a row in a celltable, each with this method:
protected void addButtonColumn(String header, final IHasValue<Row, Button> hasVal){
Column<Row, String> column = new Column<Row, String>(new TextButtonCell()) {
#Override
public String getValue(Row object) {
return ((Button)hasVal.getValue(object)).getText();
}
};
column.setFieldUpdater(new FieldUpdater<Row, String>() {
#Override
public void update(int index, Row object, String value) {
((Button) hasVal.getValue(object)).click();
}
});
table.addColumn(column, header);
}
I want each button to something different when clicked, but it doesn't work. i know that i should do something in setfieldupdater but i don't know what.
Your use of the TextButtonCell to contain a Button (i.e. a widget) doesn't really make a lot of sense - wouldn't it be easier to let the cell have access to the data, and use the ValueUpdater to trigger some kind of behavior based on that data directly?
Cells are not widgets - they are much simpler than widgets. This chiefly means two things: they are faster to draw, and stupider. Both of these things are as a result of a single cell instance being used to draw many pieces of data in slightly different ways. If you are going the effort of building a button per element, it doesn't make sense to use a cell-based widget then - you are nearly drawing everything twice, and getting the worst of both worlds (slow code, that is hard to work with).
Don't use a Button with ClickHandlers attached, but some other abstraction to deal with clicks, like a Command instance for each row, or even better, some kind of handler that accepts the row instance clicked. It might even make sense to have a FieldUpdater instance passed in as a parameter for your method (and maybe make the IHasValue generic on String instead of Button, so your models don't need to wrap widgets).
(This may not be answering your question directly, but is instead hopefully helping shed some light on why we use cells at all, and how to best write code that takes advantage of cells.)

Categories