Monthly Archives: June 2011

PyQt MenuBar Outside MainWindow

import sys, os
from PyQt4 import QtCore, QtGui
class AddressBook(QtGui.QWidget):
    def __init__(self, parent=None):
        super(AddressBook, self).__init__(parent)
        self.create_actions()
        mainLayout = QtGui.QVBoxLayout()
        toolBar = QtGui.QToolBar()
        simpleButton = QtGui.QToolButton()
        simpleButton.setDefaultAction(self.simpleAct)
        fileButton = QtGui.QToolButton()
        fileButton.setText('File')
        fileButton.setPopupMode(QtGui.QToolButton.MenuButtonPopup)
        fileButton.setMenu(self.pop_file_menu())
        editButton = QtGui.QToolButton()
        editButton.setText('Edit')
        editButton.setPopupMode(QtGui.QToolButton.MenuButtonPopup)
        editButton.setMenu(self.pop_edit_menu())
        toolBar.addWidget(simpleButton)
        toolBar.addWidget(fileButton)
        toolBar.addWidget(editButton)
        mainLayout.addWidget(toolBar)
        mainLayout.addWidget(QtGui.QGroupBox())
        self.setLayout(mainLayout)
        self.setWindowTitle("Menu By Tool Bar")
    def pop_file_menu(self):
        aMenu = QtGui.QMenu(self)
        aMenu.addAction(self.fileOpenAct)
        aMenu.addAction(self.fileCloseAct)
        return aMenu
    def pop_edit_menu(self):
        aMenu = QtGui.QMenu(self)
        aMenu.addAction(self.editCopyAct)
        aMenu.addAction(self.filePasteAct)
        return aMenu
    def create_actions(self):
        self.simpleAct = QtGui.QAction('Simple', self, triggered=self.do_nothing)
        self.fileOpenAct = QtGui.QAction('Open', self, triggered=self.do_nothing)
        self.fileCloseAct = QtGui.QAction('Close', self, triggered=self.do_nothing)
        self.editCopyAct = QtGui.QAction('Copy', self, triggered=self.do_nothing)
        self.filePasteAct = QtGui.QAction('Paste', self, triggered=self.do_nothing)
    def do_nothing(self):
        print 'do nothing'
if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    addressBook = AddressBook()
    addressBook.setGeometry(100, 100, 640, 480)
    addressBook.show()
    sys.exit(app.exec_())

How to add a QMenuBar to a QWidget instead of QMainWindow? I have no idea. But I really need a menu bar floating above all those small windows! Fortunately, QToolBar comes to save the day. A QToolButton can have a nice popup menu as well. This is a simple example.

Advertisements

Leave a comment

Filed under Python, Qt

Python Socket Server Example

We already know how to check host availability by ping, but that is not good enough. The file returned by popen() is often unreadable. And we need actual communication between client and server side. This is about how to create a simple server with Python socket.

First the class of server. It is a open-ended thread can run forever.  It always listens and waits for a client to contact. Once a connection is established, it tries to receive any message sent by client, then reply a ‘roger’. As soon as the current connection is severed, it comes back to listening again.

import socket, datetime, threading, os

class AServer(threading.Thread):
    def __init__(self, port):
        threading.Thread.__init__(self)
        self.port = port

    def now(self):
        d = datetime.datetime.now()
        return d.strftime("%d/%m/%y %H:%M:%S")

    def run(self):
        host = ''
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind((host, self.port))
        print 'server started successfully, waiting...'
        s.listen(1)
        conn, addr = s.accept()
        print 'contact', addr, 'on', self.now()

        while 1:
            try:
                data = conn.recv(1024)
            except socket.error:
                print 'lost', addr, 'waiting..'
                s.listen(1)
                conn, addr = s.accept()
                print 'contact', addr, 'on', self.now()
                continue

            if not data:
                print 'lost', addr, 'waiting..'
                s.listen(1)
                conn, addr = s.accept()
                print 'contact', addr, 'on', self.now()
            else:    
                print "received msg:", data
                conn.send('roger')

To start the server on local host at a given port:

 t = AServer(31944)
 t.start()

Now write a simple client to contact the server, make sure the host address and port is set correctly:

import socket, time, threading, sys

host = '127.0.0.1'
port = 31944

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.settimeout(3.0)
try:
    s.connect((host,port))
except socket.error:
    print host ,'is offline, stop '
    exit()

try:
    s.send('hello')
    data = s.recv(1024)
    print host, 'says:', data
except socket.error:
    print host,'is offline, stop '
    exit()

s.close()

As long as the server side is running, this will always get a ‘roger’. Because the client exit() right after receiving the first message from server. It will immediately be lost on the server side.

Leave a comment

Filed under Python

Google Reverse Image Search

Google seems to pull out another new trick: reverse image search. You can drop an image into the search bar, wait for a while, and get supposed relevant results. I have been playing with it for a while. Following two images, snapshots from news podcast. One is Ronald Reagan, the other is JFK. Both search returns good result:

The icon of VLC player leads to the site of VLC

And this blue figure actually leads todoctor manhattan!

Man, this is crazy. How does it work?

Leave a comment

Filed under Uncategorized

PyQt Connect to Hosts

This example has a few tricks:

Piling a few tree widget items based on a string list of host IP address, and each host will get a thread trying to ping the relevant address by:

os.popen('ping -q -c2 '+addr,'r')

Whether the host is available is decided by scanning the resulting file to look for ‘100% packet loss’. The decision will be send within a signal to trigger a specific tree widget item to show up green or red icon. And it uses timer.timeout signal to run all those threads every 30 seconds

Get the source here.

Leave a comment

Filed under Python

Building PyQt for Maya on Mac

To build PyQt on Mac, usually:

python configure.py
make
sudo make install

should be fine. But Maya 2008 and Maya 2009 on Mac is using the old Python 2.5. To use PyQt inside Maya, it should be specifically built  compatible with that Python comes with Maya. So:

/Applications/Autodesk/maya2009/Maya.app/Contents/Frameworks/Python.framework/Versions/2.5/Resources/Python.app/Contents/MacOS/Python configure.py
make
 sudo make install

Both Sip and PyQt should be built in this way. Resulting module will appear in /Library/Python/2.5/site-packages/

Copy everything inside to /Applications/Autodesk/maya2009/Maya.app/Contents/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/, sitting next to the maya modules.

Now to test if it works in Maya, run the minimal script in Maya SE:

import sys, os
from PyQt4 import QtCore, QtGui
app = QtGui.QApplication(sys.argv)

addressBook = QtGui.QLabel("Hello world!", None)  
addressBook.show()

A tiny window should appear if everything works as expected.

To skip the building time, download the precompiled package of PyQt and Sip. It is built and tested on Mac OSX 10.5.8.

Revised: This won’t work! Maya will be locked when PyQt is started, even when pumpThread is used.

Leave a comment

Filed under Python

PyQt Editable Label

import sys, os
from PyQt4 import QtCore, QtGui

class AddressBook(QtGui.QWidget):
    def __init__(self, parent=None):
        super(AddressBook, self).__init__(parent)

        self.nameLabel = QtGui.QLabel("untitled")
        
        self.mainLayout = QtGui.QGridLayout()
        self.mainLayout.addWidget(self.nameLabel, 0, 0)
        
        self.setLayout(self.mainLayout)
        
        self.setWindowTitle("Right-click to edit the name")
        
        self.create_actions()
        self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.setup_context_menu)
        
    def create_actions(self):
        self.startEditAct = QtGui.QAction('Edit', self, triggered = self.start_edit_name)
        
    def setup_context_menu(self, point):
        aMenu = QtGui.QMenu()
        aMenu.addAction(self.startEditAct)
        aMenu.exec_(self.mapToGlobal(point)) 
        
    def start_edit_name(self):
        self.nameEdit = QtGui.QLineEdit(self.nameLabel.text())
        self.mainLayout.addWidget(self.nameEdit, 0, 0)
        self.nameEdit.returnPressed.connect(self.finish_edit_name)
        
    def finish_edit_name(self):
        self.nameLabel.setText(self.nameEdit.text())
        self.nameEdit.hide()

if __name__ == '__main__':
    import sys

    app = QtGui.QApplication(sys.argv)

    addressBook = AddressBook()
    addressBook.show()
    addressBook.move(100, 100)
    addressBook.resize(320, 100)

    sys.exit(app.exec_())

We have a label can put some text there. That is OK until we want to change the text. Using a line edit instead could be an option, but we want the text stay there most of the time untouchable.

This problem can be solved by a simple trick. Right-click and choose the ‘Edit’ menu, a line edit will be placed over the label. Press enter when finished the editing. That will trigger a function to change the label text and hide the line edit over it.

This also brings a minimal example about how to create context (right-click-to-pull-down) menus as well as how to use signal and connect.

Get the source.

Leave a comment

Filed under Python

File Reference Basic

This document is about how to create and remove file referencing in Maya.

Say there is a file named bhdt.mb like above. New a file and run:

file -r -ns "cc" -typ "mayaBinary"  "bhdt.mb";


Will bring a bunch of Read-Only nodes that referred to what’s inside bhdt.mb

“cc” is the namespace, so everything in this reference will be named as “cc:*”

Can create more references to the same file by:

file -r -ns "dd" -typ "mayaBinary"  "bhdt.mb";
file -r -ns "ee" -typ "mayaBinary"  "bhdt.mb";
file -r -ns "ff" -typ "mayaBinary"  "bhdt.mb";
file -r -ns "gg" -typ "mayaBinary"  "bhdt.mb";

Each with its own namespace.

Put one of them under a group, then try to delete group1. This will fail because it has Read-Only children. To remove the reference, select the group1, and run:

file -rr "bhdt.mb";

dd:glb and everything under it will disappear. After the reference is gone, group1 can be deleted.

Revised:

file -r command actually returns the file name it referred to. Those names are unique. In case there are multiple references to a same file, second reference will return “bhdt.mb{1}”, and third is “bhdt.mb{2}”, and so on. These names are useful to determine individual reference when calling file -rr command.

Leave a comment

Filed under MEL