qt如何用python结合_在Qt(C++)中与Python混合编程
一、PythonQt庫
在Qt(C++)中與Python混合編程,可以使用PythonQt庫。
網(wǎng)站首頁:http://pythonqt.sourceforge.net
下載頁面:https://sourceforge.net/projects/pythonqt/files/
只提供了源碼下載,需自行編譯。
版本要求:
其網(wǎng)站building頁面上的要求:Qt 4.8.1以上,Python2.6以上
實際測試中得出的版本要求:Qt5.4以上,可以編譯得到動態(tài)鏈接庫(.so文件);Python2.7.12,編譯范例程序成功。
(備注:我的測試環(huán)境是操作系統(tǒng) Ubuntu 16.04 64bit,PythonQt版本:3.2)
二、編譯與安裝
1. 安裝Qt
去Qt網(wǎng)站下載安裝包,或者通過apt安裝。安裝完畢后,在命令行中執(zhí)行qmake -v,查看輸出信息,確認(rèn)Qt已安裝好。
注意:如果使用apt或者synaptic安裝Qt,那么需要手動安裝Qt的一些模塊,例如multimedia等。以Qt5為例,其模塊一般以libQt5為開頭,可以用apt或synaptic搜索關(guān)鍵字安裝。如果缺少模塊,則編譯時會報錯提示。
2. 安裝Python
用apt安裝Python和Python-dev。Linux一般預(yù)裝Python。
sudo apt install python python-dev
3. 編譯
將下載的源碼解壓。進(jìn)入解壓目錄,之后執(zhí)行編譯指令。假設(shè)解壓目錄為PythonQt
cd PythonQt
qmake
make all
編譯可能需要花費幾分鐘,請耐心等待。
編譯完成后,編譯得到的庫文件以及范例程序都在PythonQt/lib下。此時運行范例程序可能失敗,需要先安裝剛編譯好的庫。
4. 安裝
所謂安裝,是指讓系統(tǒng)能夠找到編譯好的庫文件。實現(xiàn)的方式有多種,這里介紹通過鏈接的方式安裝。
首先確認(rèn)系統(tǒng)中的庫文件默認(rèn)目錄是什么。
cd /etc/ld.so.conf.d/
ls
可能列出一些配置文件,文件名是對應(yīng)的目錄,比如x86_64-linux-gnu.conf。用文本編輯器打開,就可以看到對應(yīng)的完整目錄。我的系統(tǒng)中默認(rèn)庫目錄有
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
這里,我選擇/usr/lib/x86_64-linux-gnu這個目錄安裝。
#進(jìn)入PythonQt的目錄
cd PythonQt
#復(fù)制文件(文件名中的數(shù)字與版本有關(guān),不一定和我一樣)
sudo cp lib/libPythonQt-Qt5-Python2.7.so.3.2.0 /usr/lib/x86_64-linux-gnu
sudo cp lib/libPythonQt_QtAll-Qt5-Python2.7.so.3.2.0 /usr/lib/x86_64-linux-gnu
#進(jìn)入安裝目錄
cd /usr/lib/x86_64-linux-gnu/
#創(chuàng)建鏈接
sudo ln -sf libPythonQt-Qt5-Python2.7.so.3.2.0 libPythonQt-Qt5-Python2.7.so
sudo ln -sf libPythonQt-Qt5-Python2.7.so.3.2.0 libPythonQt-Qt5-Python2.7.so.3
sudo ln -sf libPythonQt-Qt5-Python2.7.so.3.2.0 libPythonQt-Qt5-Python2.7.so.3.2
sudo ln -sf libPythonQt_QtAll-Qt5-Python2.7.so.3.2.0 libPythonQt_QtAll-Qt5-Python2.7.so
sudo ln -sf libPythonQt_QtAll-Qt5-Python2.7.so.3.2.0 libPythonQt_QtAll-Qt5-Python2.7.so.3
sudo ln -sf libPythonQt_QtAll-Qt5-Python2.7.so.3.2.0 libPythonQt_QtAll-Qt5-Python2.7.so.3.2
#更新
sudo ldconfig
安裝完成。運行PythonQt/lib下的范例程序(雙擊或命令行執(zhí)行),如果可以運行,說明正常。
三、在Qt項目中使用PythonQt
可以看范例源碼和官方文檔學(xué)習(xí)。這里以Linux(Ubuntu系)環(huán)境為例,簡單介紹一下使用方法。
1. 新建項目
使用QtCreator新建項目。
2. 準(zhǔn)備庫文件
需要將一些配置文件和PythonQt庫的頭文件復(fù)制到項目文件夾下(可以新建一個子文件夾)。假設(shè)項目目錄為[PRJ],PythonQt目錄為[PYQ]。
cd [PRJ]
mkdir PythonQt
cp [PYQ]/src/PythonQt*.h PythonQt/
cp [PYQ]/build/*.prf ./
cp [PYQ]/lib/libPythonQt-Qt5-Python*.so* ./
其中.h是頭文件,.prf是配置文件,.so是鏈接庫。
頭文件可以直接使用。配置文件需要修改,主要是修改相關(guān)目錄。
說明:配置文件的注釋方式是每行前加注釋符號#。
以下是一種修改方式:
common.prf
將以下三行刪除或注釋掉:
CONFIG(debug, debug|release) {
TARGET = $${TARGET}_d
}
將所有的$$PWD/../改為$$PWD/。
PythonQt.prf
刪除或注釋掉以下內(nèi)容:
INCLUDEPATH += $$PWD/../src
# check if debug or release
CONFIG(debug, debug|release) {
DEBUG_EXT = _d
} else {
DEBUG_EXT =
}
修改
unix::LIBS += -L$$PWD/../lib -lPythonQt-Qt5-Python$${PYTHON_VERSION}$${DEBUG_EXT}
改為
unix::LIBS += -L$$PWD -lPythonQt-Qt5-Python$${PYTHON_VERSION}$${DEBUG_EXT}
3. 修改.pro文件
在項目.pro文件中加入以下內(nèi)容:
include ( common.prf )
include ( PythonQt.prf )
INCLUDEPATH += PythonQt
4. 在代碼中調(diào)用PythonQt
這個可以參考PythonQt的范例,然后慢慢摸索。
首先,引用頭文件
#include "PythonQt.h"
在使用PythonQt時,首先要對PythonQt的單例對象進(jìn)行操作。包括初始化,獲取對象等。
// init PythonQt and Python
PythonQt::init();
之后,獲取__main__模塊。
PythonQtObjectPtr mainModule;
// get the __main__ python module
mainModule = PythonQt::self()->getMainModule();
為了能看到python程序中的打印信息,需要連接PythonQt單例對象信號,與你自己寫的槽。
// connect output signals
connect(PythonQt::self(), SIGNAL(pythonStdOut(const QString&)), this, SLOT(stdOut(const QString&)));
connect(PythonQt::self(), SIGNAL(pythonStdErr(const QString&)), this, SLOT(stdErr(const QString&)));
第一個信號是向std::out的輸出,第二個信號是std::err的輸出。
之后就可以操作mainModule的方法來調(diào)用python代碼了。當(dāng)然,如果python代碼里不需要輸出,也可以不連接上述信號。
四、執(zhí)行Python語句或腳本
按照上一節(jié)的說明初始化后,就可以執(zhí)行Python語句或調(diào)用Python腳本了。
1. evalScript——執(zhí)行少量語句
如果要調(diào)用的python代碼只有單一一行語句或者少量幾語句,可以使用evalScript函數(shù)。該函數(shù)的參數(shù)是要執(zhí)行的指令,返回執(zhí)行結(jié)果。
QVariant result1 = mainModule.evalScript("19*2+4", Py_eval_input);
QVariant result2 = mainModule.evalScript("len([1, 2, 3])", Py_eval_input);
其中"19*2+4"是python語句,第二個參數(shù)表示執(zhí)行的是獨立的python表達(dá)式。返回類型是QVariant,可以根據(jù)實際執(zhí)行的語句,轉(zhuǎn)換成具體的數(shù)據(jù)類型。比如這里可以用QVariant::toInt()轉(zhuǎn)換成int,得到的結(jié)果分別是42和3。不熟悉的朋友請參考QVariant文檔。
evalScript 可以用于定義函數(shù),方便以后調(diào)用。例如:
mainModule.evalScript("def add(a, b):\n return a+b");
這樣就定義了一個Python中的函數(shù),名為add,接受兩個參數(shù)a和b,返回兩個數(shù)的和。
后面第三部分介紹如何調(diào)用Python函數(shù)。
2. evalFile——執(zhí)行腳本
如果需要使用Python實現(xiàn)較為復(fù)雜的功能,寫在一個Python文件中比較方便。假設(shè)文件名為func.py。
Python文件的開頭需要加入如下語句:
from PythonQt import *
在Qt項目中新建資源文件(.qrc文件),在資源文件中添加func.py,以便調(diào)用。調(diào)用方式為:
mainModule.evalFile(":/func.py");
調(diào)用時的文件路徑與添加到資源文件時的前綴有關(guān)。注意evalFile沒有返回類型,所以不能用于獲得返回值,可以通過第四節(jié)所說的打印信息看到執(zhí)行過程(如果Python程序中有輸出語句的話)。如果是Qt GUI項目,也可以把執(zhí)行結(jié)果顯示在界面上,這一點在后面第四部分介紹。
執(zhí)行過evalFile后,腳本中定義的函數(shù)可以在以后直接調(diào)用。所以可以把需要返回值的功能寫在函數(shù)中,后續(xù)調(diào)用。調(diào)用方式見第三部分。
3. call——調(diào)用函數(shù)
前面介紹了,使用evalScript和evalFile都能定義Python函數(shù)。定義的函數(shù)會保存,之后可以在代碼的任意位置調(diào)用。要調(diào)用這些函數(shù),可使用call。例如第一點介紹中定義了一個Python中的函數(shù),名為add,接受兩個參數(shù)a和b,返回兩個數(shù)的和。調(diào)用該函數(shù)的方法如下:
int a = 2;
int b = 3;
QVariant c = mainModule.call("add", QVariantList() << a << b);
call 的第一個參數(shù)是要調(diào)用的函數(shù)名稱,用字符串表示;第二個參數(shù)是要調(diào)用的Python函數(shù)的參數(shù),用一個QVariantList存放所有參數(shù)。這里,我們把a和b兩個數(shù)傳入。返回類型是QVariant,需要轉(zhuǎn)換成具體類型。這里的c轉(zhuǎn)換成整數(shù)后是5。
4. addObject——與Qt交互
如果Python程序需要與Qt中的對象交互,可以將繼承自QObject的類型實例傳入Python中。addObject就起到這個作用。
假設(shè)Qt GUI項目的mainwindow中有一個label,下面演示怎么通過Python改變label的文字。
首先將label傳入Python(label的類型是QLabel,繼承自QObject),并且賦予其一個在python中調(diào)用的變量名:
mainModule.addObject("label", ui->label);
這條語句將ui->label傳入,并且在Python中可以用label這個變量名調(diào)用。
Python程序如下:
def changeLabelText(text):
label.text = text
通過evalScript或者evalFile調(diào)用上述程序后,再用call調(diào)用。
mainModule.evalFile(":/func.py");
mainModule.call("changeLabelText", QVariantList() << QString("Hello"));
mainModule.call("changeLabelText", QVariantList() << QString("World"));
第一次調(diào)用將標(biāo)簽文字改為Hello,第二次調(diào)用改為World。
在Python中操作QObject對象時,要注意,使用的方法、函數(shù)、屬性等要用Python語法進(jìn)行。例如在Qt(C++)中改變標(biāo)簽文字的方法是
label->setText("Hello");
而在Python中,應(yīng)該使用
label.text = 'Hello'
5. Python模塊路徑問題
既然使用Python,可能是要使用Python中成熟的庫,例如用于科學(xué)計算的NumPy。如果在Python程序中寫入:
import numpy as np
可能在使用PythonQt執(zhí)行的時候報錯,說找不到numpy模塊。(當(dāng)然是已安裝的情況下,在Python或命令行中都運行正常。)這很可能是路徑問題。
首先找到numpy的安裝路徑,例如/usr/lib/python2.7/dist-packages。然后在需要調(diào)用的Python文件中加入如下語句:
import sys
sys.path.append('/usr/lib/python2.7/dist-packages') # To use Numpy
import numpy as np
這樣就可以正常導(dǎo)入NumPy模塊了。
小結(jié)
以上介紹了PythonQt庫的安裝和使用方法。
更加復(fù)雜的功能,請參考PythonQt源碼中的范例,以及網(wǎng)站上的文檔。
開發(fā)者文檔:http://pythonqt.sourceforge.net/Developer.html
源碼中也有很多有用信息,關(guān)于一些API函數(shù)的調(diào)用,可以參考頭文件中的注釋。例如,關(guān)于上面介紹的evalScript等函數(shù),可以參考PythonQtObjectPtr.h文件(可用Qt Creator內(nèi)的切換功能快速定位)。
總結(jié)
以上是生活随笔為你收集整理的qt如何用python结合_在Qt(C++)中与Python混合编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何阻止ajax自动重定向_重发和重定向
- 下一篇: ehcache springboot_S