Chris Crawford

Ranch Hand
+ Follow
since Jun 22, 2011
Chris likes ...
Mac OS X
Cows and Likes
Total received
In last 30 days
Total given
Total received
Received in last 30 days
Total given
Given in last 30 days
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Chris Crawford

Mr. Silverman, I wonder how much of the huge change in the programming culture is cause and what is effect. Are programming languages immensely more complicated because the Internet makes it possible to get help from others? Most people end up learning about computers from their peers -- has the Internet vastly expanded the set of peers, thereby vastly expanding the complexities of computer systems? If so, I think that we'll eventually have to dump the charity approach used in places like this website. There will be more and more people needing more and more help with more and more complicated technologies, and we'll need full-time helpers to make all this possible -- which in turn means that we need a model that pays them for their efforts.

I just now noticed the PIE system on this website, and bought some pie. Lord knows I owe you guys a lot. How well has the PIE system worked out? Is the end result fair to the contributors?
1 year ago

I remember many people I trusted that definitely considered you on the short list for "Great Atari Programmers", at least in terms of results.  

Well, yes, I think I can claim to have mastered everything about the Atari HCS. But that was a simple system. The 6502 was a beautifully clean CPU with a delightful instruction set. The HCS did have a number of tricky features, most notably the Display List Interrupt. However, I was 30 years old and full of the young man's cognitive intensity. I could keep all the variables in a big assembly language program in my head. Nowadays it's all I can do to juggle just one ball...

Nowadays, languages like Java are immensely more complicated than the 8-bit machines we played with forty years ago. Does anybody believe that there is a person on this planet who has mastered every single Class and Interface in the standard set? When was the last time you used the FormatFlagsConversionMismatchException class? Or the InternalFrameFocusTraversalPolicy class? I'll bet that, buried somewhere deep in there is a BalanceTheFederalBudget Class and an ImplementWorldPeace Interface.

We were able to put together everything that you could know about the HCS in a technical document less than 200 pages long. By contrast, there are hefty books just explaining Swing. The fact that there are so many sites on the web (of which this one is arguably the best) devoted to Java gives an idea of just how immense this technology is. I just checked and there are 389 THOUSAND topics in the "Beginning Java" section of the forum, and 290 thousand topics in the "Java in General" section. I doubt that there were as many as 10 thousand programmers using the Atari back then.

The Atari Pond was so small that it was easy to be the biggest fish in the pond back then. Nowadays, though, the Java Ocean is so big that I feel like a bacterium floating in it. I have enormous respect for the people who have devoted their time to learning a big hunk of this monster. I'm too busy with other things: designing interactive storytelling systems, teaching, fixing my tractor, reforesting my land... sheesh. So thanks again to everybody for the help!
1 year ago
It's not reading the file that triggers the listener; it's stuffing its values into the various UI devices. The program is an editor. The user loads a file. The file contains numbers and strings that the user can edit. The program loads the file and puts some of the numbers and strings into text edit boxes, spinners, buttons, and sliders so that they can be edited. The act of putting these numbers and strings into various devices triggers a ChangeEvent. The processing of the change event was causing other undesirable effects.
1 year ago

...but we would still like to see fo ourselves what the code looks like that is going wrong.

There are two overall processes that cause trouble. The first is program initialization during which I'm setting up UI elements and their listeners. This wasn't difficult to handle. The real difficulty comes with the second step, during which I am loading data from a file. This data must be stuffed into the various control devices, which in turn triggers their listeners. A file can be loaded at any time during program execution, and because control devices influence each other (storing one kind of data into button A can enable or disable spinner B, for example), I don't want those devices triggering events while I'm loading data from the file. This is why I prefer to just disable all listeners during initialization and file loading.

It's true that a careful analysis of the sequence of initialization and file loading would enable me to optimize the sequence so that improper events wouldn't be triggered. But the hours I spend on that improvement would not be usable for the more important design issues I'm struggling with.

As to global variables, I grew up on FORTRAN and assembler, where everything was global! I've learned enough to greatly reduce my use of globals, but there remain a few areas that are troublesome. In particular, because their scope is not the same as the class they're working within, event handlers are particularly difficult for me, so I end up falling back on globals occasionally.
1 year ago
Thanks again for the suggestions. I have indeed solved the problem by assiduously implementing the isCompletelyInitialised variable throughout every nook and cranny of the code. I am now advancing to other, even dumber mistakes. Onward!
1 year ago
I think you nailed it. This old dinosaur is still locked into the old procedural model of code execution, and it never occurred to me that various Listeners might intervene during initialization, but in fact that's what happened. Initializing a spinner triggered its ActionListener, which in turn caused it to modify leftButton. I was sure that it had to happen during the code that I copied here, but sneaky old Java pulled that trick under the table.

Is there a standard way to prevent Listeners from activating during initialization? I had experienced a similar problem with another program some years ago and solved it by setting up a global boolean that blocked action by Listeners during initialization. At the outset of initialization, isInitializing = true. Every Listener had as its first statement an if-statement checking the value of isInitializing. At the end of initialization, isInitializing is set to false. It's my kind of programming solution: crude, inefficient, but effective. There HAS to be a better way. Is there?
1 year ago
First off, I'm not a real programmer, although I've been writing code for over fifty years. For me, programming is a means, not an end, so I minimize my knowledge to what is necessary to get the job done -- and usually the programming is not the primary effort in my work. I explain this to caution you that I really don't know that much about Java, even though I've been using Java for nearly 20 years and I have written tens of thousands of lines of code in Java.

So here's my problem: my code is illegally overwriting a variable. Here are four lines of code, with their output:

Thus, writing a value to the variable centerSpinner overwrites the value of the variable leftButton -- which has nothing whatsoever to do with centerSpinner! These two variables are both class-level variables in the same class.

This is not a huge complicated program; it doesn't have any big data structures. No images, no big buffers. The data structures it uses fit into an 86 KB XML file. The problem hits right at the launch of the program, so it's not some sort of memory leak.

I noted that the memory usage of Eclipse when this happened was 1.03 GB, which leads me to suspect that Eclipse was working with a 1.00 GB memory allocation and overran. But shouldn't I have gotten an OutOfMemoryError?  I ran another program I'm working on, and it worked fine even though Eclipse was using 1.06 GB of memory.

I spent some time looking through discussions here on CodeRanch about OutOfMemoryErrors and garbage collection, which convinced me that it will cost me several days to learn enough about this to work this out myself.

I'm not asking anybody to solve my problem for me; what I'm asking is whether this problem looks like excessive consumption of memory despite the contraindications.
1 year ago
You should be supervising young coders. It's true that they have just as much technical expertise as you do on the latest technologies, but technical expertise is not the measure of a good programmer. Good programmers have been burnt by stupid problems so many times that they have a well-developed sense of how to plan things to avoid those problems.

Here's another way of thinking about it: a young programmer plunges into coding immediately and gets the code written in an hour, then spends twenty hours debugging it. The old pro spends five hours thinking and planning, then writes the code in two hours, and it works perfectly the first time.

Let the young whippersnappers stay on top of the latest developments, while you concentrate on teaching them good project habits.

By the way, did you know that the 6502 opcode for loading a fixed byte into the accumulator is $A9? 😛
1 year ago
For the time being I have a workaround: I drop the newly-written XML file into my text editor and erase all the groups of whitespaces, then save that copy. Yes, it's a hack, but it's easier than fighting Java, which is like fighting an octopus with one hand tied behind your back. I'll keep fooling around. My next exploration will be of older programs that used XML files.
1 year ago
Thanks much for the quick answer!

My problem here is that the method that SAVES the XML file is pretty-printing it, but the method that LOADS the file, of course, rejects the pretty-printed XML. So I start with a proper XML file, it loads correctly, I make a tiny edit, then save the XML file. Examining it in a text editor, I see that it is pretty-printed. When I then try to load the XML file into my program, the program of course chokes on the pretty-printed file.

By the way, I do have this line of code inserted into both the load and save methods:


So, should I work on the save method, trying to get it to NOT pretty-print?
Or should I work on the load method, trying to get it to work with pretty-printed XML files?
1 year ago
Here's a weird one: I've been using an XML parser with Java for more than 15 years. XML parsers are a bit messy, but they work -- until now. I have a long XML file, but managed to trim the problem down to three lines. These three lines are parsed correctly:

But these three lines produce screwy results:

Now, to make this even more screwball, the insertion of tabs is made by the method that saves the XML file -- which uses the same java xml libraries! In other words, the java xml libraries write files that they cannot read!

The two java XML libraries that I am using are java.xml and java.xml.crypto from JDK 15.0

This is just too crazy. Somehow, somewhere, I must be doing something wrong. But this code has worked in the past. My best guess now is that it is somehow arising from the latest JDK and JVM. Perhaps they're mismatched. But I never had this problem before I updated to the latest version of Eclipse and the latest JVM.

Do you think I need to take some sort of psychoactive drug to comprehend the problem? 😄
1 year ago
I stumbled on the solution, and it's ridiculously simple: replace this

myGraphics2D.drawImage(myImage, myX, myY, new Color(0,0,0,0), null);

with this:

myGraphics2D.drawImage(myImage, myX, myY, null);

In other words, simply refuse to specify any background color. It does make more sense this way; Rob's observation was on the mark. Earlier, the Java people had created a possibly confusing situation by permitting the upper version of drawImage code to function EXACTLY as described. Or perhaps I should say that their specification for the performance of the method permitted two possible interpretations. That is, until recently, specifying a transparent background color drew the transparent pixels as transparent. However, the lower version of drawImage was also in place, and it specified that it would draw transparent pixels as transparent. There were thus two ways to get a transparent background, and apparently somebody objected to the double meaning. I don't see a problem here; I think that they should have left it alone. But instead they decided to modify the upper version of drawImage so that it ignores the alpha channel in the specified background color. Perhaps they did so because, in their minds, it made no sense. In any case, I'm sure that some older Java apps will be tripped up over this.

Problem solved. Thanks so much for all the help!
4 years ago
Thanks for the suggestions. It appears that I have not made myself clear. Here's an image showing what the program previously produced and what it now produces:

On the left is the original result; on the right is the current result. As you can see, the image of the face has its transparent pixels drawn properly on the left, but on the right, it substitutes black pixels. This, again, is the culpable line of code:

myGraphics2D.drawImage(myImage, myX, myY, new Color(0,0,0,0), null);

I greatly appreciate Piet for reassuring me that I haven't lost my mind. I will attempt to try other definitions of the transparent Color, then I'll try drawing using the background blue color. My reticence for doing this is that in different situations I must draw different background colors, and transferring that information to this drawing method will be a bit of a bother.

Thanks again for the help, and I'll report back with results!
4 years ago
Thanks for the fast response! As it happens, I had already stumbled upon the "Backgrounds with Transparency" page to which you linked. It seemed closest to my problem, but it relies on method "setOpaque(boolean)", which cannot be applied anywhere in my program, because I don't use any Swing components -- it's all AWT.

I double-checked the Graphics2D.drawImage(Image, int, int, Color, ImageObserver) and its description has one oddity; it states:

"Transparent pixels are drawn in the specified background color."

My assumption has been that the specified background color can also contain an alpha value, and so can be set to be transparent. That's certainly what the definition of the class Color says. Yet for some reason, Graphics.drawImage(...) refuses to implement the alpha channel of the specified background color.

What's especially frustrating is that this code worked perfectly back in 2013. I have screen shots showing it functioning exactly as intended. And yet something has changed in the five years since then. Perhaps Java is undergoing the same kind of creeping senility that I've been experiencing for the last few years.

Another frustration is the transparency is implemented properly for all the drawing methods. It seems to be refusing to recognize transparency only with drawImage.

I'll keep trying various experiments. Perhaps implementing a real ImageObserver will help. I'll also try drawing that fragment offscreen and then simply pasting it into the main image.
4 years ago
I searched through the answers here and found nothing relevant to my problem, likely because my problem is so weird.

About five years ago I wrote a little program (only about 2,000 lines long). For rather complicated reasons, I confined my graphics code to AWT. I got everything working just fine.

This morning I resurrected the program to show to somebody else. But now it doesn't draw properly. Specifically, this line of code inside the paint() method malfunctions:

myGraphics2D.drawImage(myBufferedImage, myX, myY, new Color(0,0,0,0), null);

(I've revised the code to be more readable.) As I wrote earlier, this line has always worked fine. But now, five years later, it fails to apply the alpha value -- which is 0 -- to the drawing. Instead, it draws black for the pixels that are transparent in the BufferedImage. If I change "new Color(0,0,0,0)" to "new Color(255,0,0,0)", then it draws red where it should be transparent.

No, I'm not using setOpaque(boolean) anywhere, because that's a method in the JComponent class, and I am not using any kind of JComponent. Indeed, my import statements do not include anything from Swing.

Here is a complete list of every single type of drawing method my program uses:


That's all I'm using to draw to the window. I have tried a number of experiments, none of which have proven to be illuminating. I don't think that the use of "null" for the required ImageObserver parameter inside the drawImage call is the source of the problem, because other things work well.

I realize that you would like to see the entire program, but it's 2,000 lines long, and has a complex structure that would take some time to understand. I've tried to think of a way to boil it down to the absolute bare minimum, but there's a lot of cross-dependency in the drawing routines, so I doubt that this approach would be useful.

Does anybody have any ideas as to why I have lost transparency that I once had? Did Java AWT change sometime in the last five years?
4 years ago