2013-09-07 70 views
10

Tôi đang phát triển một ứng dụng GUI theo định hướng toán học trong Qt/C++ và muốn nhúng một tập lệnh Python, bao gồm NumPy và Matplotlib. Sử dụng Python C API, cuối cùng tôi đã quản lý để chạy một kịch bản, lấy các giá trị từ các biến Python, bao gồm các mảng NumPy vv Nhưng tôi đã thất bại trong việc vẽ các biểu đồ Matplotlib vào ứng dụng Qt/C++ của mình. Nó là tốt hơn để nói, tôi đã quản lý để lưu đệm RGBA của biểu đồ để một biến bằng cách sử dụng kịch bản Python, sau đó nhận được giá trị của biến như một PyObject của loại bộ đệm, có được bộ đệm và biến nó thành QImage sau đó để QPixmap và cuối cùng đặt nó vào QLabel và hiển thị nó.Nhúng biểu đồ matplotlib vào ứng dụng Qt/C++

Nhưng tôi vẫn thiếu hành vi tương tác, thay đổi kích thước, v.v ... có vẻ như nó có thể được thực hiện bằng cách chuyển tiếp các sự kiện chuột Qt tới figure.canvas.button_press_event nhưng sau đó nó quá phức tạp ... không hiểu các nguyên tắc của Python nhúng đủ tốt. Tôi thiếu cái gì đó hiển nhiên.

Tôi tìm thấy một số mẫu nhúng biểu đồ matplotlib vào PyQt hoặc PySide (ví dụ: viết bằng Python) ứng dụng mà tôi đã thấy một cái gì đó như QMainWindow.setCentralWidget (canvas) hoặc layout.addWidget (canvas). Ở đây canvas là đối tượng FigureCanvasQTAgg (http://matplotlib.org/api/backend_qt4agg_api.html).

Điều này cho thấy rằng canvas kế thừa từ QWidget. Nhưng khi tôi cố gắng bắt chước điều này trong mã C++ bằng cách sử dụng C API của Python, tôi kết thúc bằng một khung hình PyObject *, không biết làm thế nào để trasform nó thành một QWidget. Đây là đoạn trích của tôi mà không có bước quan trọng:

//draw a figure in Python script called from C++ app 
PyRun_SimpleString("import matplotlib\n" 
"matplotlib.use('Qt4agg')\n" //use Qt4 backend 
"import pylab\n" 
"pylab.plot(randn(10))\n" //plot something 
"fig = pylab.gcf()\n" //take current figure 
"canvas = fig.canvas" //canvas is of FigureCanvasQTAgg type 

//get canvas as PyObject 
PyObject* m = PyImport_AddModule("__main__"); 
PyObject* canvas = PyObject_GetAttrString(m, "canvas"); 
//from what I know, canvas is a PyObject wrapped around an object derived from QWidget 

//... 
//... here I do not know how to convert canvas (i.e. PyObject) into canvasWidget (i.e. QWidget)??? 
//... 

//show chart as a widget 
MyWindow.setCentralWidget(canvasWidget) 

Như tôi đã viết, tôi phải bỏ lỡ điều gì đó hiển nhiên. Tôi googled ở khắp mọi nơi nhưng không thành công. Bất kỳ trợ giúp sẽ được rất đánh giá cao.

+0

Đây là một câu hỏi tò mò, bạn muốn bọc trong C++ trình bao python của một lớp C++;) Bạn đúng là 'HìnhCanvasQTAgg' _is_ một đối tượng' QWidget', nhưng tôi cũng không biết đủ về việc nhúng để có được một tham chiếu đến đối tượng QT bên dưới. – tacaswell

+0

tcaswell - Vâng, đây chính xác là những gì tôi cần - trích xuất tham chiếu hoặc con trỏ hoặc bất kỳ QWidget nào từ PyObject. –

+0

Đề xuất duy nhất của tôi là xem xét chính xác những gì 'PyQt' hoặc' PySide' đang làm bên dưới. – tacaswell

Trả lời

2

Đối với PySide, tôi khuyên bạn nên đọc this comp.lib.qt.pyside thread và cũng là phần trên type converters trong tài liệu PySide. Tôi không thể xác minh tính chính xác tuyệt đối của this code, nhưng dường như bạn làm điều mình muốn.

Đối với PyQt, the same comp.lib.qt.pyside thread liên kết đến ví dụ về unwrapping SIP objects, đó chính xác là những gì bạn cần.

+3

Bạn có thể tóm tắt nội dung của liên kết không? Họ nhìn đúng, nhưng liên kết thối làm giảm sự hữu ích lâu dài của câu trả lời này. – tacaswell