Brian Cole

Author
+ Follow
since Sep 20, 2005
Merit badge: grant badges
For More
Cows and Likes
Cows
Total received
In last 30 days
0
Forums and Threads

Recent posts by Brian Cole

Chris Mary wrote:Hi,

Below is the code
The problem is after the image is written, the font size is small when i opened it


The text drawn on the image will be about 32 pixels tall, since you specified 32 as the font size.

Whether or not that should be considered "small" is subjective. The image itself has a height of 2437 pixels, so 32 would be about 1.3% of that.

If you want a bigger font, then change the 32 to something else, like 128, or image.getHeight()/10. [But if you use image.getHeight()/10 then you will probably also want to change the Y value in the call to drawString().]
2 years ago
Here's a quick driver for the ComboBoxCellEditor in the posting above, which I used so I could test it (minimally) before posting.

Well, it's not so quick, because my TableModel takes 100 lines of code. But the rest of it is fairly quick. The three rightmost column of the table each have their own custom ComboBoxCellEditor, set in lines 165-167.
2 years ago
I don't know where the code on codejava.net comes from, but IMHO their CountryCellEditor is not quality code.

Here's their implementation:Lines 38-42 create a new instance of JComboBox and populate its entries, which is slow. The idea is that this method should be fast. Speed is crucial in a Cell Renderer, and definitely not as crucial in a Cell Editor, but this method is called when the user clicks a cell for editing. The ComboBox should be already set up (as much as possible) before this method is called, so that the user does not perceive a delay. This code could be changed to instantiate the ComboBox, and populate its entries, in the constructor.

Line 44 is appropriate. If the code were changed to instantiate the ComboBox in the constructor, this line would still appear here in the getTableCellEditorComponent() method.

Line 45 is setting an ActionListener on the ComboBox. This is appropriate, so that when the user hits the enter key the Cell Editor will finish editing, rather than remaining in the cell and requiring the user to hit the escape key or click somewhere to actually complete the edit. But there are problems:
  • Presuming that we have improved the code by only instantiating the ComboBox only once, then the action listener needs to be added only once, outside of this method.
  • Having the CountryCellEditor actually implement the ActionListener interface, and adding this as the listener, is an old coding style. Modern code would probably structure this differently. But it could work with this structure, except...
  • But what it's actually doing in the actionPerformed() method (lines 58-59) isn't quite right. It is taking the selected value and storing it in the country instance variable, so it can later be returned by the getCellEditorValue() method, which I guess is fine. [If the ComboBox were an instance variable, then wouldn't need to keep country as a separate variable but could simply have getCellEditorValue() return cb.getSelectedItem()—no ActionListener needed to get getCellEditorValue() to work correctly.] But the ActionListener is not doing anything else. It's not notifying the table that the edit has completed, and it should.


  • Lines 47-51 are misguided, I think. This would be appropriate for a Cell Renderer, not so much for a Cell Editor. It's possible that something like this could work in a Cell Editor, but it would take some experimentation. As the very least, I think line 50 is setting the wrong color. It would be more appropriate to setBackground(table.getBackground()). That is, to match the ComboBox's background with the table's (regular non-selected) background, rather than to the table's (selected) foreground. But I think it would probably be best to skip these lines entirely and let the ComboBox have its default background.

    They declare the CountryCellEditor class itself (lines 16-17) is like this:I can understand why they want to extend AbstractCellEditor because that way they inherit a bunch of event-handling methods and don't have to mess with them. But I think I would prefer to do it like this instead:This way, the Cell Editor is a JComboBox, which I kind of like better, but the trade-off is that we then need to implement those event-handling methods (which isn't too bad). But the other way could work too. This is simply my preference.

    Anyway, my code might look something like this:
    2 years ago

    Brian Cole wrote:Math.floor() is your friend.
    [edit: Many edits. Replaced the original naive implementation with an ugly-ish one. Fought with the syntax highlighter.]

    This does detect, to 3 places, that:

  • 3.1756 is the same as 3.175
  • -3.1756 is the same as -3.175
  • 0.0 is not the same as Double.NaN
  • 2.3e304 is not the same as 2.4e304


  • I guess this refactoring does the same thing more efficiently:

    Campbell Ritchie wrote:

    Tim Holloway wrote:The whole question is bogus. . . . .

    Agree. I hope there isn't some lecturer giving their students that sort of question.


    Not sure I completely agree, but the question should have been phrased with care.
    2 years ago

    Harold Tee wrote:Methinks the string approach is simpler.

    Mind you, you still have that age old problem with math operations which amplify the storage precision,
    e.g isEqual ( (2.3 / 10.0) , 0.23) will not be equal.



    This code is sort of doing it twice. Once you've assigned truncated values to a and b, you could simply compare them and be done with it. Or, if you're going to do the String.format("%.3f", a) conversion to String anyway, you needn't have truncated them to three digits first. Or am I missing something?
    2 years ago

    Campbell Ritchie wrote:No, the cast rounds towards 0, so you get 5678.



    Darn it, I’m embarrassed to have made this mistake. In my memory casting double to int truncated, but I wanted to be sure so I checked the JLS (https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3) before posting. The JLS says values are rounded but, as you say, they are “ rounding toward zero”. I misread it. That’s what I get for posting from my phone without checking.

    That said, I still think Math.floor() is better than casting. Math.floor() returns a double, so we never leave the floating-point realm. It might still have overflow problems, if the exponent is within three of maximum maybe, but for example  it will handle NaNs better than casting.

    I haven’t tried these dynamic Java execution thingies yet. Sounds like I should.
    2 years ago
    I agree that this seems like an example question that expects the answer to be simple. I also agree that it’s probably best not to convert to strings, though I think that method could work.

    Someone suggested casting to int (or long) but I don’t think that’s a good idea, because it rounds the value. So (int)(x*1000) will turn 5.6789 to 5679, not 5678 [edit: no it doesn’t; see post below]. Could fix this by subtracting 0.5 or something, but that seems unnecessarily complicated.

    Math.floor() is your friend.
    [edit: Many edits. Replaced the original naive implementation with an ugly-ish one. Fought with the syntax highlighter.]

    This does detect, to 3 places, that:
  • 3.1756 is the same as 3.175
  • -3.1756 is the same as -3.175
  • 0.0 is not the same as Double.NaN
  • 2.3e304 is not the same as 2.4e304

  • Unfortunately, due to overflow it does not detect that 2.3e305 != 2.4e305. They look the same when multiplied by 1000, because 2.3e308 is out of range for a double.
    2 years ago
    I still don't know how you're instantiating your JFormattedTextField but, if it were me doing it, it would look something like this:


    Note that in lines 26–40 I override the field's commitEdit() method. You could take those lines out and it would work, sort of. The problem is that if the user types a plain number into the field, without the leading '$' character (or whatever is expected for the local currency) then NumberFormat.parse() fails and the field's value will not be set. Overriding commitEdit() like this is somewhat ugly, but allows the user to set the value with an undecorated number.

    I should point out that if I were doing this for real, I wouldn't have the money field, which needs to be synchronized with the field's value, as this code does with the PropertyChangeListener. I would simply let the value reside inside field, and call getValue() when it was needed [perhaps preceded by commitEdit()].
    2 years ago
    I'm going to try to be helpful without reading this entire thread thoroughly, which is a recipe for disaster but here we go.

    First thing, be aware that calling commitEdit() is supposed to throw ParseException sometimes. That it is happening is not necessarily a problem. Especially since you have called jCost.setFocusLostBehavior(javax.swing.JFormattedTextField.COMMIT), which means that you want the field to retain invalid content even when it loses focus.

    Second, I'd like to reinforce what Mr. McLeod said about calling commitEdit() before calling getValue(). This is a good idea. In fact, on page 713 of my book (Java Swing 2nd Ed., O'Reilly, 2003) it says

    value [meaning the property returned by getValue()] is the most recent valid content of the field, which may not be the current content of the field if an edit is in progress. Because of this, it is usually wise to call the field's commitEdit() method before calling getValue().*

    *Especially if the focusLostBehavior property is set to PERSIST. In other cases it is likely that the field lost focus (causing its value to be committed or reverted) when the user clicked on the button or other GUI element that resulted in this call to getValue(). Calling commitEdit() is easy enough that it makes sense to do it unless you're sure that it isn't required.


    But I should point out that I'm not saying that commitEdit() should be called in a FocusListener. In fact, that sounds like a bad idea. I simply mean that every place in your existing code where you call getValue(), you should call commitEdit() on the previous line.

    How are you actually creating your currency field? Is it like this?
    disclaimer: I'm only one of several authors of my book, but I'm the one who happened to write the JFormttedTextField chapter (chapter 20). However that was two decades ago and I haven't used them much since then. For this post I had originally written two paragraphs which, upon further reflection, I decided was incorrect so I removed them.
    2 years ago
    To expand on what Mr. Camick said, this is controlled by the ButtonModel. If you read the text at the top of the ButtonModel javadoc (at, for example, https://docs.oracle.com/javase/8/docs/api/javax/swing/ButtonModel.html ) it says the following:

    Pressing the mouse on top of a button makes the model both armed and pressed. As long as the mouse remains down, the model remains pressed, even if the mouse moves outside the button. On the contrary, the model is only armed while the mouse remains pressed within the bounds of the button (it can move in or out of the button, but the model is only armed during the portion of time spent within the button). A button is triggered, and an ActionEvent is fired, when the mouse is released while the model is armed - meaning when it is released over top of the button after the mouse has previously been pressed on that button (and not already released).



    So, if you do the ActionListener thing, you should be getting the behavior you say you want, unless someone has messed with the ButtonModel.
    2 years ago
    Does extends BasicToolTipUI not work? Does it need the SynthContext stuff?
    2 years ago

    Tim Holloway wrote:I ended up getting a big fat O'Reilly book on Swing and discovering the Sun Swing tutorials. Hopefully the book has been updated, since I just checked and it's for Java version 1.2!



    I'm waking a zombie to mention that the big fat O'Reilly "Java Swing" book was updated in 2002 for JDK 1.4. Even though that was 20 years ago, it's not terribly out of date. Obviously it doesn't use lambdas for event listeners and such, since the book predates Java lambdas.

    The older edition that you have is more severely out of date. Neither edition was intended as a tutorial, though they do develop some examples one could learn from.

    disclaimer: I'm one of the authors of the 2002 edition.
    2 years ago

    Campbell Ritchie wrote:That could have shown return this; or return new Test3();


    The point is that the method is called, so any side-effects do happen, but what value it returns is irrelevant.

    By the way: which section in the JLS?


    It's in §15.11.1. (BTW, I happen to be looking at the Java SE 7 edition of the JLS.)
    5 years ago

    Campbell Ritchie wrote:You can still write rubbish like...and it will both compile and run with the expected result.


    I agree. In fact the JLS shows this nifty example:
    What I was trying to get at was there was, at one point in the distant past (for Java), a time when the javac compiler was handling nullInstance.staticMethod(...) incorrectly w.r.t. the JLS.

    When this was discovered they either changed the compiler or changed the JLS, but I can't find any corroborating details. I've spent a few minutes googling and have struck out. I guess it's possible it never happened and I made it up.

    it would have been clearer to just write Animal.staticMethod(...) and be done with it


    I realized what you were doing. In saying this I was not trying to imply otherwise, was just trying to answer your "which one is actually executed?" question for the benefit of others. I apologize for being less than clear.
    5 years ago

    Ricky Bee wrote:but let me rephrase my previous question (and steer it a little from the inheritance of a static method problem which originated it in the first place):


    FYI, one should be careful using the term inheritance with static methods. Which is not to say that a subclass can't inherit static methods, because they often do, but it's best to be precise.

    In Campbell Ritchie's example, for example, the Lion class does not inherit the method staticMethod() from Animal because it's hidden by its own implementation of staticMethod(). Here hidden is a formal term defined by §8.4.8.2 of the Java Language Specification. (See also the first sentence of §8.4.8.)

    Ricky Bee wrote:is such a structure a common-place in Java programing? I mean, is it normal to instantiate an object from a superclass and then pass it an object from a subclass?


    I would say it's somewhat common. For example, in my code I often write
    Now this isn't quite the same, because List is an interface and not a class, but the concept is the same.
    I want the rest of my code to treat myList as a generic List without presuming any specific implementation. Then later I can easily change the implementation from ArrayList to something else (such as LinkedList) if I want.

    To use Campbell Ritchie's example...
    ...it wouldn't be unusual to do
    and it would be even less unusual to use a Collection instead of an array. Consider
    where it's kind of happening twice. The List's type parameter is Animal but the each element of myList is a some subclass of Animal. And also the type of myList is List but the asList() method will return a particular implementation of List.

    In swing this of course happens all the time, with java.awt.Component, javax.swing.JComponent, and all the subclasses of JComponent. When you write myPanel.add(new JButton("text")) the type of the argument is Component but you're passing it instance of JButton. And calling myPanel.getComponents() returns an array of type Component[] but each element of the array will be some particular subclass of Component. (But this isn't quite what you were asking.)
    5 years ago