Empty rows in a QTableWidget with lots of images

To be fair, I don’t know if it’s so many images or so many rows that cause a QTableWidget to show empty rows (or cellwidgets and TableWidgetItems not to appear, however you want to think about it). I think it has something to do with images (I use Pixmaps in labels), because it seems like the bigger the image data I try to display in each row, the earlier the QTable Widget will show its first empty row.

Why does it do this? How do you fix it?

I have no idea. I didn’t see anything about it in my searching.

But I have a hack. Oh yes.

I noticed if you resize the window, it will repaint the images clustered around the rows visible in the viewport at that moment. In other words, if you have a hundred rows, and the top half is OK and the bottom half is empty, if you scroll down to the bottom and resize the window, the bottom half will be OK and the top half will be empty.

So, um — why not programmatically resize the window — just a pixel — when the user scrolls down a certain amount?

First, connect the vertical scrollbar of the table like so (my extended MyTableWidget object is the “self” in this case):

self.connect(self.verticalScrollBar(), QtCore.SIGNAL(“valueChanged(int)”), self.displayedRegionChanged)

somewhere in the MyTableWidget init() method, store the parentWidget (assuming it is your window)

class MyTableWidget(QTableWidget) :

   def __init__(self, parentWidget):

      super(MyTableWidget, self).__init__(parentWidget)
      self.parentWidgetObj = parentWidget

and then add a method like so:

def displayedRegionChanged(self, newVerticalValue):

   #Trigger for deciding we must repaint
   #
   repaintingThreshold = self.verticalScrollBar().maximum()/4

    if abs(newVerticalValue – self.oldVerticalValue) > repaintingThreshold :

       if self.resizeToggle :
          self.parentWidgetObj.resize(self.parentWidgetObj.width()+1, self.parentWidgetObj.height())
       else :
          self.parentWidgetObj.resize(self.parentWidgetObj.width()-1, self.parentWidgetObj.height())
       self.resizeToggle = not self.resizeToggle

       self.oldVerticalValue = newVerticalValue

(To review, I use:

Mac OSX
PyQt4
and py2app to deploy, not that it is relevant in this case.)

ANJOI!

macdeployqt output

PyQt and py2app: Seriously I don’t know what to do with you when you’re like this

OK. For some crazy reason I needed to display jpegs in my python application. I know! I am a wild woman! Somebody get me chamomile and sweatpants!

I’m going to spend a while telling you how you CAN’T get jpegs to show up. If you want you can skip this part and go down to where it says “DO NOT BE SCARED.”

No problem:

  • designing a UI in Qt Designer
  • writing the application in python
  • using Pixmaps to display images — pngs! jpegs! gifs! Whee!
  • creating an app with py2app (once you’ve got it successfully installed — and that is no mean feat. I’m looking for the link that saved me…)

Medium problem:

  • Getting the ” you might be loading two sets of Qt binaries” error to go away.

You can do this by including a blank qt.conf file in your application’s Resources folder (myApp.app/Contents/Resources). macdeployqt will make a qt.conf file for you — more on that later.

Big problem:

  • Seeing the jpegs when I run the app

(more…)

Fun with PyQt — Setting alignment of all paragraphs in a QTextEdit

Hey, kids! You wanna center-align all the text in a Text Edit input?

You might have noticed that QTextEdit.setAlignment() only applies the new alignment to the current paragraph. You may also have noticed there’s no handy method for iterating through paragraphs. You may also have noticed that, if you use the nice QTextCursor.movePosition() method that returns a boolean to let you know when you’re done, it doesn’t actually move the text edit’s cursor — but if you use QTextEdit.moveCursor(), it doesn’t return a boolean. Oops.

Here’s what I did:

   def setAlignment(self, textEdit, desiredAlignment):

   #Make sure the cursor is at the start of the text field
   #

   textEdit.moveCursor(QtGui.QTextCursor.Start)

   lastPosition = -1
   currPosition = textEdit.textCursor().position()
   while lastPosition != currPosition :
      textEdit.setAlignment(desiredAlignment)
      textEdit.moveCursor(QtGui.QTextCursor.Down)
      lastPosition = currPosition
      currPosition = textEdit.textCursor().position()

    #Move to the end of the text field in preparation for whatever comes next
   #

   textEdit.moveCursor(QtGui.QTextCursor.End)

Woot!

PyQt: Seriously what are you doing

Oh, QTableWidgetItem. Why don’t you have a mouseReleased method? Or a rightClicked() signal? I sure would like you to listen to right-clicks, but you do not. I tried adding a cellWidget (instead of an item) to my QTableWidget cell, but then that scuttles all the sweet selection indicators of a decent, God-fearing table cell.

Blarrrrrrrrrrrrgh.

No matter. I will work around. I didn’t want to right-click anyway. My work around will be much better. These are not sour grapes. These are sweet grapes. Sweet, sweet grapes.

PyQt4: I hate you

No, that’s not true… if I didn’t love Qt Designer and python so much, I wouldn’t tolerate PyQt, so I must secretly love PyQt. UGH BAD LOVE. And py2app is like the foul-smelling friend of PyQt that comes around once a week to get both of them drunk and loud at 3:00 AM.

So I spent the entire morning checking, tweaking and re-checking my import statements, my .profile, my paths, my app, my resources, my plugins — all because my library source wasn’t making it into my py2app-generated app. You know — these source files that are imported in every one of my python modules? Yeah, not there. Didn’t make the cut. Sorry.

I checked my notes from the LAST time I went through this, with no results. I Googled. I checked forums. I googled again. I emacsed. I sourced. I logged and moved and copied and pasted.

And then a little after lunch a tiny voice said “Why don’t you use the –no-strip flag?”

That voice was smart. A little bit of this action got me a working app:

python setup.py py2app –include sip –no-strip

Yeah, at 44 Mb it’s kind of fatty. But you know what I’m gonna do about that. NOTHING.

FOR A WHILE.

But NOW… oh ho ho NOW my jpeg-based thumbnails aren’t showing up. You wanna know why? Because apparently Qt’s jpeg support is a plugin. The last time I had to tangle with a plugin was phonon, and that worked OK until PyQt’s failure to wrap an obscure phonon object caused a persistent and deadly threading error. How did I get around that, you ask? I DIDN’T. I used the built-in python modules wave and pyaudio and rewrote what I had been getting from phonon. Don’t talk to me about phonon. Phonon is dead to me!

Anyhoo. Such is technology.

Time to copy over some plugins…

**Update 5:07 PM**

I had been getting this message when my application attempted to load a jpeg-based QPixmap:


On Mac OS X, you might be loading two sets of Qt binaries into the same process. Check that all plugins are compiled against the right Qt binaries. Export DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.
QObject::moveToThread: Current thread (0x13b11f40) is not the object’s thread (0x1e8760).

I found this. All I did was add a blank qt.conf to the myApp.app/Contents/Resources folder, and this error ceased. You’ll notice that’s all the bug-tracker describes — how to get the error to go away — not how to get the imageformats plugin to work.

I am still trying all sorts of different things to get my application to pick up the imageformats’ jpeg plugin… Will update…

Update 3/5

Nope. Couldn’t make the plugin happen. Fortunately — VERY fortunately — I had the option and ability to convert and store the JPEGs as PNGs on-the-fly, so I can use PNGs, which are native to Qt and work ju-u-u-ust fine when all apped up.

Someday I’ll be able to make an apped-up Qt plugin work, but it hasn’t happened yet.

Update 9/1

After much research and experimentation I came to this conclusion about trying to use plugins in a py2app-generated PyQt app: I can’t. But there’s a workaround.

Silent Printing from Java

Hey.

Are you having trouble printing from Java?

Do you have a perfect PDF — maybe one you made with iText — but when you print it the edge is cut off?

And you have checked and double-checked your Java, and nothing seems to be wrong?

Hmmm?

Here is a helpful hint — make sure your page size is LETTER, and not, say ISO A4. I know you are too smart to confuse the two, but if you are presumptive and did not check Wikipedia and just remember that one time you were in Office Depot and they seemed like the same, mebs you might make this mistake and struggle with it for two days. Mebs.

Point is, A4 is a little longer and a little skinnier than LETTER — enough to cut off some of your beautiful letter document.

.

If you use iText, make your document size like this:

Document document = new Document(PageSize.LETTER);

Or if you are feeling sassy and landscape-y, like this:

Document document = new Document(PageSize.LETTER.rotate());

.

And when you print, do like this (super simple and dangerous, assuming printer can handle everything, using default and printing silently, etc.):


DocFlavor flavor = DocFlavor.INPUT_STREAM.PDF;
DocAttributeSet printAttributes = new HashDocAttributeSet();
printAttributes.add(MediaSizeName.NA_LETTER);

PrintService defaultService = PrintServiceLookup.lookupDefaultPrintService();

DocPrintJob job = defaultService.createPrintJob();

System.out.println(“Printing ” + outputFilePath + ” to ” + defaultService.getName());

InputStream inputStream;
try {
inputStream = new FileInputStream(outputFilePath);
Doc doc = new SimpleDoc(inputStream, flavor, printAttributes);

try {
job.print(doc, null);
} catch (PrintException e) { e.printStackTrace(); }

} catch (FileNotFoundException e1) { e1.printStackTrace(); }

Or… you know what? If you’re on a Mac, and you want to live even MORE dangerously? (Or maybe just eliminate the possibility of problems with your document, rather than your printing?) SHA-POW:


try {

Runtime.getRuntime().exec(“lp ” + outputFilePath);

System.out.println(“Successfully printed ” + outputFilePath);
} catch (IOException e) {
System.out.println(“Document ‘” + outputFilePath + “‘ failed to print.”);
}

HA HA HA HA. I AM A MAD HAXOR.

(Also, incidentally, iText has an Executable.java class with a silent printing method, but I couldn’t get it to work. Not that that sez anything.)

How Software Development is like Drug Dealing

So I`m going back to school. As an undergraduate, again, which is weird, and makes me think, oh crap, have I gone through a wormhole to 1996? I don’t want to write static HTML and drink instant and get up at 5:30 AM to watch Samurai Pizza Cats and hear everybody doing the Sling Blade voice french fried pertaters mm-hmm WTF OMG!!!1 I don’t know if I`m ready to be 18 again, or like father, like son, or even trading places. I mean, sure, I can handle the first day of school and essays and final exams and parties without beer (ooh, that was a shudder), but the thing that worries me most is leaving the steady supply of mortgage payments and yogurt cups that comes from working in software.



Who’s that developer wa-a-a-ay at the bottom of the food chain? Mm, tastes like plankton!

I`m not going to miss lying awake trying to figure out how to unit test JavaScript — or worse, having nightmares that I`m sick and I have to debug myself (all world’s ditch-diggers and medical students commence crying me river). But what I tell people is that programming computers is like dealing drugs: nobody grows up thinking, “Hey, I want to be a programmer!” — but once you start doing it you can’t stop `cause of the money. I don’t really know about dealing, of course, but I watch a lot of Law and Order.

I said as much to a fellow programmer/dealer, and he mentioned a couple of other similarities. So here, officially, is the master list of reasons my job is like dealing drugs:

  • There’s always somebody over you who owns the product. You own nothing — not even the gas-guzzling `99 Jeep Cherokee you bought with your gruesome profiteering.
  • You are utterly at the whim of the customers — the *users*. If you can’t give `em the good stuff fast enough and clean enough they`ll find another source or worse: quit using.
  • You can’t talk about your work with your family because no one wants to hear about it.
    “You see, Hibernate handles your object-relational database mapping, and it’s much better than OJB because you won’t need your own prox-“
    “ZZZzzz.”
    If you were on a blind date (which, in your line of work, they`d all probably have to be) you`d probably do well to say you did something else. Architect is good.
  • You make promises about your product you can’t possibly keep (Longhorn, PS3, there are no bugs, first one’s free, etc.)
  • Your product has no shelf life. No matter what it is or how great it is, in three years it`ll be garbage.
  • After a few years of excitement and growth, you`ll never do anything new. Same stuff, different language. Twenty years in the industry programming in the highest-end most beautiful Java-Ruby-Smalltalk-kinda language and you`ll still find yourself writing a register/login/logout sequence. Again. This time with feeling.

Anyway.

You know Lucas Black? The kid from Sling Blade and American Gothic who would have made a good Anakin Skywalker? He’s almost 22. I probably could have figured this out already but I didn’t see Cold Mountain. Where was the legality-countdown for this one?