PySide ドラッグ&ドロップ
忘れがちなポイント
- setAcceptDrops(True)
- 各イベントでevent.accept
- ファイルパスはTextじゃなくてURL
from PySide import QtCore, QtGui import sys, os class DragAndDrop(QtGui.QLabel): def __init__(self): super().__init__() self.setText('Drag and drop here') self.setAlignment(QtCore.Qt.AlignCenter) self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) self.setAcceptDrops(True) def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.accept() else: event.ignore() def dragMoveEvent(self, event): if event.mimeData().hasUrls(): event.setDropAction(QtCore.Qt.CopyAction) event.accept() else: event.ignore() def dropEvent(self, event): filename = os.path.basename(event.mimeData().urls()[0].path()) self.setText(filename) if __name__ == '__main__': app = QtGui.QApplication(sys.argv) w = DragAndDrop() w.show() sys.exit(app.exec_())
QMessageBoxでチョロっとダイアログ表示
import sys from PySide import QtGui app = QtGui.QApplication(sys.argv) icon = None QtGui.QMessageBox.about(icon, 'About', 'Hello.') QtGui.QMessageBox.question(icon, 'Question', 'Are you dead?', QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) QtGui.QMessageBox.information(icon, 'Info', 'You are dead!', QtGui.QMessageBox.Ok) QtGui.QMessageBox.warning(icon, 'Warn', 'You are dead!', QtGui.QMessageBox.Ok) QtGui.QMessageBox.critical(icon, 'Error', 'You are dead!', QtGui.QMessageBox.Ok)
戻り値は君の眼で確かめてみてくれ!
Pythonでウインドウハンドル取得してGetClientRectしてみる
WIN32から離れられない貴方へ
import sys from PySide import QtGui import ctypes class RECT(ctypes.Structure): _fields_ = [('left', ctypes.c_long), ('top', ctypes.c_long), ('right', ctypes.c_long), ('bottom', ctypes.c_long)] class TestWidget(QtGui.QWidget): def __init__(self): super().__init__() def resizeEvent(self, event): super().resizeEvent(event) # ここから! ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p] hwnd = ctypes.pythonapi.PyCapsule_GetPointer(self.winId(), None) rect = RECT() ctypes.windll.user32.GetClientRect(hwnd, ctypes.byref(rect)) print(rect.left, rect.top, rect.right, rect.bottom) if __name__ == '__main__': a = QtGui.QApplication(sys.argv) w = TestWidget() w.show() sys.exit(a.exec_())
参考記事
Widgetを等倍で中央寄せさせておきたい!
QScrollAreaのresizeEventを継承してゴニョゴニョしたら割と簡単にできた
import sys from PySide import QtCore, QtGui class AlwaysCenterAlign(QtGui.QScrollArea): def __init__(self): super().__init__() self.setAlignment(QtCore.Qt.AlignCenter) self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) def resizeEvent(self, event): super().resizeEvent(event) v = self.verticalScrollBar() h = self.horizontalScrollBar() v.setValue(v.minimum() + (v.maximum() - v.minimum()) / 2) h.setValue(h.minimum() + (h.maximum() - h.minimum()) / 2) def wheelEvent(self, _): pass def keyPressEvent(self, _): pass if __name__ == '__main__': a = QtGui.QApplication(sys.argv) s = AlwaysCenterAlign() l = QtGui.QLabel() l.setPixmap(QtGui.QPixmap('lena.jpg')) s.setWidget(l) s.show() sys.exit(a.exec_())
RaspberryPi 3 RPIOでサーボモーターを動かす
RPIOをインストール
モーターは デジタル・マイクロサーボ SG90 を使いました
下記サイトを参考に github.com
こんな感じでインストール
cd ~ git clone https://github.com/metachris/RPIO.git --branch v2 --single-branch cd RPIO sudo python3.4 setup.py install
スクリプトを書く
root権限で実行しないといけないっぽい
from RPIO import PWM import time servo = PWM.Servo() pin = 14 def deg_to_width(deg): ''' 角度からパルス幅に変換 :param: deg 角度(-90~+90) :return: パルス幅 ''' center = 127 margin = 45 step = (center - margin) / 90.0 deg = max(-90.0, min(deg, 90.0)) return int(center + deg * step) * 10 while True: for x in [-90, 0, 90, 0]: servo.set_servo(pin, deg_to_width(x)) time.sleep(1)
ちなみにPWMとPCMは同時に使えないのでサーボ制御しながら音も出したいときはBluetoothスピーカーとかUSBサウンドカードを使ったほうがよさげ
QActionでコードもすっきり
メニューやツールバーを実装するときはQPushButtonやコールバックをガリガリ書くのではなくQActionを作る。QActionオブジェクトを作成しておけば、複数のメニューやツールバーをまたいでも、ひとつのQActionオブジェクトで挙動を定義できるし、QActionGroupを使えばラジオボタンも作れる。ショートカットキーやIconも設定できる。
import sys from PySide.QtCore import * from PySide.QtGui import * # ラジオボタン的な挙動をするメニューを作る例 if __name__ == '__main__': myapp = QApplication(sys.argv) window = QMainWindow() # まずはExclusiveなグループを作成 exclusive_group = QActionGroup(window) exclusive_group.setExclusive(True) # グループに属するアクションを作る def createExclusiveAction(in_name, in_icon, in_shortcut): action = QAction(in_name, window) action.setActionGroup(exclusive_group) action.setIcon(myapp.style().standardIcon(in_icon)) action.setShortcut(in_shortcut) action.setCheckable(True) return action data = [ ('Play', QStyle.SP_MediaPlay, 'Q'), ('Pause', QStyle.SP_MediaPause, 'W'), ('Stop', QStyle.SP_MediaStop, 'E'), ('Forward', QStyle.SP_MediaSeekForward, 'R'), ('Backward', QStyle.SP_MediaSeekBackward, 'T'), ] actions = [] for name, icon, shortcut in data: actions.append(createExclusiveAction(name, icon, shortcut)) # メニューバーとツールバー両方に追加して動作テスト menubar = window.menuBar() mediamenu = menubar.addMenu('Media') toolbar = window.addToolBar('ToolBar') for x in actions: mediamenu.addAction(x) toolbar.addAction(x) window.show() sys.exit(myapp.exec_())
ラズパイ起動時にBluetooth接続してwav再生
自分の環境でちゃんと動く記事が無かったのでメモ。設定ファイルをあちこち編集するのは好きじゃないのでbash_profileで頑張った。Linuxめんどい。
環境
- Raspberry Pi 3 Model B
- OS 2016-11-25-raspbian-jessie
1. モジュールインストール
sudo apt-get install pulseaudio pavucontrol pulseaudio-module-bluetooth reboot
2. 準備(GUIからTerminal起動してやった)
pulseaudioを起動
pulseaudio -D
ペアリング
bluetoothctl > scan on > (BluetoothスピーカーをペアリングモードにしてMACアドレスが表示されるまで待つ) > scan off > pair FF:FF:FF:FF:FF:FF # BluetoothスピーカーのMACアドレス > connect FF:FF:FF:FF:FF:FF # BluetoothスピーカーのMACアドレス > trust FF:FF:FF:FF:FF:FF # BluetoothスピーカーのMACアドレス > quit
デバイスの設定
- メニュー ⇒ Sound & Video ⇒ PulseAudio Volume Control
- ConfigurationメニューからALSAの出力先をOffにしておく
3. 起動スクリプトを用意
.bash_profileをユーザーのホームディレクトリに作成
pulseaudio -D sleep 5 # 適当にウェイト bluetoothctl << EOF power on connect FF:FF:FF:FF:FF:FF # BluetoothスピーカーのMACアドレス quit EOF sleep 5 # 適当にウェイト pacmd set-sink-volume 1 32767 # 音量調節(デバイス番号、音量~65565) aplay test.wav # wavを再生
CUIモードにしてreboot