一半君的总结纸

听话只听一半君

Embed any application into PyQt widget with QX11EmbedContainer

目的是想把任意一个程序A插到PyQt widget里,用于没有A的python module的情形下

下面拿gedit做实验,首先开个gedit,然后可以用xwininfo拿到他的 window id

[oglop@localhost]$ xwininfo 

xwininfo: Please select the window about which you
          would like information by clicking the
          mouse in that window.

xwininfo: Window id: 0x5400018 "VLC media player"

  Absolute upper-left X:  977
  Absolute upper-left Y:  54
  Relative upper-left X:  0
  Relative upper-left Y:  0
  Width: 752
  Height: 560
  Depth: 24
  Visual: 0x20
  Visual Class: TrueColor
  Border width: 0
  Class: InputOutput
  Colormap: 0x22 (installed)
  Bit Gravity State: NorthWestGravity
  Window Gravity State: NorthWestGravity
  Backing Store State: NotUseful
  Save Under State: no
  Map State: IsViewable
  Override Redirect State: no
  Corners:  +977+54  -2111+54  -2111-466  +977-466
  -geometry 752x560+977+31

然后这样就可以

import sys
import subprocess
from PyQt4 import QtCore, QtGui

wid = 0x5400018

class MyDialog(QtGui.QDialog):

    def __init__(self, parent=None):
        super(MyDialog, self).__init__(parent)
        layout = QtGui.QVBoxLayout()
        container = QtGui.QX11EmbedContainer()
        container.embedClient(wid)
        layout.addWidget(container)
        self.setLayout(layout)

app = QtGui.QApplication(sys.argv)
win = MyDialog()
win.show()
sys.exit(app.exec_())

但是有个问题是,我要如何用subprocess开gedit,然后得到他的问window id? 好像没什么直接的简单办法,/proc//environ里的WindowID不是我要的.

脑残法找wid

import sys
import subprocess

cmd = 'gedit'
process = subprocess.Popen(cmd,stdout=subprocess.PIPE, shell=True)
pid = str(process.pid)
# pid = '22222'

def run_command(cmd):

    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
    output = ''
    while True:
        line = proc.stdout.readline()
        if line.strip() != '':
            output += line
        else:
            break

    return output


cmd = 'xwininfo -root -children|sed -e "s/^ *//"|grep -E "^0x"|awk \'{ print $1 }\''

output = run_command(cmd)

# print output

print output.strip().split('\n')
print 'pid:',pid
for wid in output.strip().split('\n'):
    pid_cmd = 'xprop -id {wid} _NET_WM_PID|cut -d\'=\' -f2|tr -d \' \''.format(
        wid=wid)
    output = run_command(pid_cmd).strip()
    # print 'checking', '[%s]' % output
    if output == pid:
        print 'found wid:',wid
        break

# now we get wid

但不是所有程序都会设置_NET_WM_PID, 上面试验的gedit可以倒是,试了下smplayer, vlc都可以。但是没法用代码直接从pid得到xwindow id. lz想了个脑残法,想要运行什么的时候,先在/tmp建个symlink,然后通过他去开程序,然后使用类似上面的脑残法找CMD_LINE

待续 …



参考:
How to get window ID from process ID
Bug 420587 – The value of WINDOWID env var isn’t correct.
Is there a linux command to determine the window IDs associated with a given process ID?

Advertisements

One response to “Embed any application into PyQt widget with QX11EmbedContainer

  1. wen 十一月 23, 2016 @ 12:56 上午

    Win32 下干过同样的事,更蛋腾的是用winAPI进行UI 包裹

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: