Page 1 of 3 123 LastLast
Results 1 to 15 of 33

Thread: PyQT in LW

  1. #1
    automator of tasks xchrisx's Avatar
    Join Date
    Jul 2003
    Location
    Nevada
    Posts
    593
    Blog Entries
    6

    PyQT in LW

    Im starting to make the transition over to Python from Lscript (slowly ) and was curious if anyone has got a UI from PyQT inside of LW working and if so what their workflow was. Any info would be greatly appreciated.

    thanks,
    Chris
    My Lscript Collection | LinkedIn
    3D Generalist IGT

  2. #2
    Code Muppet evenflcw's Avatar
    Join Date
    Feb 2003
    Location
    Stockholm, Sweden
    Posts
    2,642
    PyQT... are you sure that is necessary? Both XPanels and LWPanels are available in the Python SDK (and I assume they work). Unless you are doing something totally new that goes beyond current LW gui paradigm you shouldn't need anything more. With LWPanels you should also have enough to build your own variants of LW controls similar to how you can build your own controls in lscript by drawing and processing mouse inputs... but with less limits and cleaner code (I believe the New Scene Editor would be mostly custom controls created using LWPanels). The only other reason I can think of for not using XPanels or LWPanels is simply not liking their syntax or whatnot.

    (Check the C SDK documentation to see what you can do with XPanels and LWPanels.)
    Last edited by evenflcw; 07-02-2012 at 02:17 PM.

  3. #3
    automator of tasks xchrisx's Avatar
    Join Date
    Jul 2003
    Location
    Nevada
    Posts
    593
    Blog Entries
    6
    I haven't yet dug too deep into the LW SDK as far as interface gui goes but if it is anything like the quirky Lscript interface I would prefer to avoid it. Also, I am branching out into other 3d software as well as my own custom non-3d tools (where pyqt can be utilized for interfaces) and I was hoping to reduce the amount of application specific interface code like LWPanels and find something more uniform. That was my main reason for wanting to see if pyqt is possible. If that sounds like a pipe dream please feel free to let me know .
    My Lscript Collection | LinkedIn
    3D Generalist IGT

  4. #4
    Code Muppet evenflcw's Avatar
    Join Date
    Feb 2003
    Location
    Stockholm, Sweden
    Posts
    2,642
    I haven't ever used QT. But I would think building your own gui with PyQT would be a bigger task than to use the gui toolkits available in the SDK of each package. But perhaps the reuse will offset that. Personally not a fan of customized guis that are an ill fit to the overall theme of the host program. I like 3rd party tools to seem as integrated as everything else. So beware, I am abit negative from the start! And to also mimic the style for each host program in QT would reasonably take longer than using what's available.

    If I had to do this, I'd use each package sdk for the gui (to get the 100% native controls, look and feel; assuming they are sufficient), but make sure to add an extra layer to abstract/extract the common gui interactions needed across the different implementations. Call it MVC, MVVM or whatnot.

    Looking forward to hear what someone with actual QT experience has to say.

  5. #5
    automator of tasks xchrisx's Avatar
    Join Date
    Jul 2003
    Location
    Nevada
    Posts
    593
    Blog Entries
    6
    Hey I don't mind the negativity as long as its constructive. Especially if it makes me think about something I may have overlooked . As far as the whole "not fitting" into the program, I prefer added functionality rather than making it match the look of the program. But yes, anyone with QT experience please chime in.
    My Lscript Collection | LinkedIn
    3D Generalist IGT

  6. #6
    Super Member Red_Oddity's Avatar
    Join Date
    Feb 2003
    Location
    A thousand years from here
    Posts
    3,352
    Hey Chris, as promised, here's a simplified PyQt UI test that works in LW.

    As you can see, it is hardly optimal, nor is my code clean, but it shows what is possible.

    Another nice experiment is looking into interactive QT UI plugins (should be possible when you create your own exec loop for Qt by calling processEvents on the QApplication)

    Code:
    import lwsdk
    from PyQt4.QtCore import Qt, QString, SIGNAL
    from PyQt4.QtGui import QApplication, QVBoxLayout, QPushButton, QLineEdit, QHBoxLayout, QFileDialog, QMainWindow, QWidget, QDialogButtonBox
    
    __author__     = "Sven Neve"
    __date__       = "July 17 2012"
    __copyright__  = "House of Secrets"
    __version__    = "1.0"
    __maintainer__ = "Sven Neve"
    __email__      = "sven"
    __status__     = "Test"
    __lwver__      = "11"
    
    class MainWindow(QMainWindow):
        def __init__(self):
            QMainWindow.__init__(self)
            self.filename = None
            self.addWidgets()
            #connect signals to UI elements
            self.btn.clicked.connect(self.choose_file)
            #attach event listener to MainWindow
            self.connect(self, SIGNAL('filenamechanged'), self.show_file)
            #show the MainWindow
            self.show()
    
        def addWidgets(self):
            #create some UI elements
            self.btn = QPushButton(QString("Choose File"))
            self.text = QLineEdit()
            self.btnbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
            cw = QWidget()
            hbox = QHBoxLayout()
            hbox.addWidget(self.text)
            hbox.addWidget(self.btn)
            vbox = QVBoxLayout()
            vbox.setMargin(0)
            vbox.addLayout(hbox)
            hbox2 = QHBoxLayout()
            hbox2.addWidget(self.btnbox)
            vbox.addLayout(hbox2)
            cw.setLayout(vbox)
            self.setCentralWidget(cw)
            flags = self.windowFlags()
            #resize MainWindow
            self.setMaximumHeight(24)
            self.setMinimumWidth(400)
            self.setWindowTitle("PyQt Dialog Test")
            self.setWindowFlags(flags | Qt.WindowStaysOnTopHint )
    
        def choose_file(self):
            filename = QFileDialog.getOpenFileName(self, 'Open File', '.')
            self.filename = filename
            # emit signal, notifying the MainWindow that the filename has changed
            self.emit(SIGNAL('filenamechanged'))
    
        def show_file(self):
            self.text.setText(self.filename)
            
    class QtDialogTest(lwsdk.IGeneric):
        def __init__(self, context):
            super(QtDialogTest, self).__init__()
            self.app = QApplication([])
            self.do_it()
    
        def do_it(self):
            self.app.main = MainWindow()
            # connect signals to Ok Cancel buttonbox
            self.app.main.btnbox.accepted.connect(self.do_accept)
            self.app.main.btnbox.rejected.connect(self.do_cancel)
    
            # Start the main loop.
            # Or, you can optionally tie it into your own main loop or the main 
            # loop of your host app and then update the Qt UI by calling
            # app.processEvents() rather than app.exec_()
            self.app.exec_()
    
            #clean up the app after the window closes
            del self.app
            return lwsdk.AFUNC_OK
    
        def do_accept(self):
            #check if there's a file name in the line edit
            if self.app.main.filename :
                print("do something with %s" % self.app.main.filename)
            else:
                print("Guess no file was selected or we canceled")
            self.app.main.close()
    
        def do_cancel(self):
            print("Canceled")
            self.app.main.close()
    
    ServerTagInfo = [
                        ( "Python QtDialog Test", lwsdk.SRVTAG_USERNAME | lwsdk.LANGID_USENGLISH ),
                        ( "QtDialog Test", lwsdk.SRVTAG_BUTTONNAME | lwsdk.LANGID_USENGLISH ),
                        ( "Utilities/Python", lwsdk.SRVTAG_MENU | lwsdk.LANGID_USENGLISH )
                    ]
    
    ServerRecord = { lwsdk.GenericFactory("LW_PyQtDialogTest", QtDialogTest) : ServerTagInfo }
    Last edited by Red_Oddity; 07-18-2012 at 07:39 AM.
    I have no special talents. I am only passionately curious. - Albert Einstein
    visit my company site : House of Secrets
    visit my personal site : svenneve.com

  7. #7
    Super Member Red_Oddity's Avatar
    Join Date
    Feb 2003
    Location
    A thousand years from here
    Posts
    3,352
    Here's an example that uses it's own loop (tied to a timer/wait loop), which during the UI refresh also refreshes LW.
    Note: don't run this plugin again when it is still running (it WILL crash LW) as i didn't build in a function that checks for existing instances.

    Again, not the best code example, there's probably much much better and safer ways to do this, but this might help people in the right direction when using 3rd party UI frameworks.

    Code:
    import lwsdk
    from PyQt4.QtCore import Qt, QString, SIGNAL
    from PyQt4.QtGui import QApplication, QVBoxLayout, QPushButton, QLineEdit, QHBoxLayout, QFileDialog, QMainWindow, QWidget, QDialogButtonBox
    import time
    
    __author__     = "Sven Neve"
    __date__       = "July 17 2012"
    __copyright__  = "House of Secrets"
    __version__    = "1.0"
    __maintainer__ = "Sven Neve"
    __email__      = "sven"
    __status__     = "Test"
    __lwver__      = "11"
    
    class MainWindow(QMainWindow):
        APP_RUNNING = False
    
        def __init__(self):
            QMainWindow.__init__(self)
            self.APP_RUNNING = True
            self.filename = None
            self.addWidgets()
            #connect signals to UI elements
            self.btn.clicked.connect(self.choose_file)
            #attach event listener to MainWindow
            self.connect(self, SIGNAL('filenamechanged'), self.show_file)
            #show the MainWindow
            self.show()
    
        def addWidgets(self):
            #create some UI elements
            self.btn = QPushButton(QString("Choose File"))
            self.text = QLineEdit()
            self.btnbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
            cw = QWidget()
            hbox = QHBoxLayout()
            hbox.addWidget(self.text)
            hbox.addWidget(self.btn)
            vbox = QVBoxLayout()
            vbox.setMargin(0)
            vbox.addLayout(hbox)
            hbox2 = QHBoxLayout()
            hbox2.addWidget(self.btnbox)
            vbox.addLayout(hbox2)
            cw.setLayout(vbox)
            self.setCentralWidget(cw)
            flags = self.windowFlags()
            #resize MainWindow
            self.setMaximumHeight(24)
            self.setMinimumWidth(400)
            self.setWindowTitle("PyQt Dialog Test")
            self.setWindowFlags(flags | Qt.WindowStaysOnTopHint )
    
        def choose_file(self):
            filename = QFileDialog.getOpenFileName(self, 'Open File', '.')
            self.filename = filename
            # emit signal, notifying the MainWindow that the filename has changed
            self.emit(SIGNAL('filenamechanged'))
    
        def show_file(self):
            self.text.setText(self.filename)
            
    class QtDialogTestCL(lwsdk.ILayoutTool):
        def __init__(self, context):
            super(QtDialogTestCL, self).__init__()
            self.app = QApplication([])
            self.do_it()
    
        def do_it(self):
            self.app.main = MainWindow()
            # connect signals to Ok Cancel buttonbox
            self.app.main.btnbox.accepted.connect(self.do_accept)
            self.app.main.btnbox.rejected.connect(self.do_cancel)
    
            # Start the main loop.
            while self.app.main.APP_RUNNING:
                self.app.processEvents()
                lwsdk.command("RefreshNow")
                time.sleep(0.01)
    
            #clean up the app after the window closes
            del self.app
            return lwsdk.AFUNC_OK
    
        def do_accept(self):
            #check if there's a file name in the line edit
            if self.app.main.filename :
                print("do something with %s" % self.app.main.filename)
            else:
                print("Guess no file was selected or we canceled")
            self.app.main.APP_RUNNING = False
            self.app.main.close()
    
        def do_cancel(self):
            print("Canceled")
            self.app.main.APP_RUNNING = False
            self.app.main.close()
    
    ServerTagInfo = [
                        ( "Python QtDialog Test Custom Loop", lwsdk.SRVTAG_USERNAME | lwsdk.LANGID_USENGLISH ),
                        ( "QtDialog Test CL", lwsdk.SRVTAG_BUTTONNAME | lwsdk.LANGID_USENGLISH ),
                        ( "Utilities/Python", lwsdk.SRVTAG_MENU | lwsdk.LANGID_USENGLISH )
                    ]
    
    ServerRecord = { lwsdk.GenericFactory("LW_PyQtDialogTestCL", QtDialogTestCL) : ServerTagInfo }
    Last edited by Red_Oddity; 07-18-2012 at 08:35 AM.
    I have no special talents. I am only passionately curious. - Albert Einstein
    visit my company site : House of Secrets
    visit my personal site : svenneve.com

  8. #8
    automator of tasks xchrisx's Avatar
    Join Date
    Jul 2003
    Location
    Nevada
    Posts
    593
    Blog Entries
    6
    Thanks for the examples, very much appreciated.
    My Lscript Collection | LinkedIn
    3D Generalist IGT

  9. #9
    automator of tasks xchrisx's Avatar
    Join Date
    Jul 2003
    Location
    Nevada
    Posts
    593
    Blog Entries
    6
    Unfortunately I couldn't get it to work. I installed PyQT in my Python 2.7 folder (both are 32 bit) and I get the error:

    ImportError: DLL load failed: %1 is not a valid Win32 application.

    I also tried to use the sys.append and point to the PyQT folder. As a last resort I even added them to my PYTHONPATH system variable and still a no go. Anyone have any suggestions of what I am doing wrong or ideas of maybe how to fix this?
    My Lscript Collection | LinkedIn
    3D Generalist IGT

  10. #10
    Super Member Red_Oddity's Avatar
    Join Date
    Feb 2003
    Location
    A thousand years from here
    Posts
    3,352
    That error usually has to do with mismatched modules for different architectures.

    I think your LW (i take it it is the 32bit version), is importing from a wrong path.
    I have no special talents. I am only passionately curious. - Albert Einstein
    visit my company site : House of Secrets
    visit my personal site : svenneve.com

  11. #11
    automator of tasks xchrisx's Avatar
    Join Date
    Jul 2003
    Location
    Nevada
    Posts
    593
    Blog Entries
    6
    Yes I am running LW 64 bit. Does that mean I have to have the Python 2.7 64bit and PyQT 64 bit installs to work properly with them?
    My Lscript Collection | LinkedIn
    3D Generalist IGT

  12. #12
    Kamehameha Chameleon BigHache's Avatar
    Join Date
    Sep 2006
    Location
    Future Past Life
    Posts
    1,899
    Just an FYI, it was stated officially that XPanels was not working yet in Python. Two updates have come out since but I have not seen a statement that says it is now fully functioning.

  13. #13
    Super Member Red_Oddity's Avatar
    Join Date
    Feb 2003
    Location
    A thousand years from here
    Posts
    3,352
    Quote Originally Posted by xchrisx View Post
    Yes I am running LW 64 bit. Does that mean I have to have the Python 2.7 64bit and PyQT 64 bit installs to work properly with them?
    Yes.
    I have no special talents. I am only passionately curious. - Albert Einstein
    visit my company site : House of Secrets
    visit my personal site : svenneve.com

  14. #14
    Registered User
    Join Date
    Jan 2011
    Location
    Israel
    Posts
    16
    Guys. if i am writing my tool using PyLW instead of LScript, is there any option to create GUI visualy, like i did a while ago with LScript Interface Builder or whatever it called, for my LScript? Handcoding GUI isn't fun at all RubyMotion, are you listening?! :P

  15. #15
    Kamehameha Chameleon BigHache's Avatar
    Join Date
    Sep 2006
    Location
    Future Past Life
    Posts
    1,899
    I'm afraid not, no. Believe me that was one of the first questions I had.

Page 1 of 3 123 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •