QTreeWidgetItemでアイコン複数表示
HTMLを表示するdelegateを用意するのが手っ取り早い
コードはここらへんを参考に
PyQt版の回答をゴニョゴニョして作成
import sys from PySide import QtCore, QtGui class RichTextDelegate(QtGui.QStyledItemDelegate): def paint(self, painter, option, index): option_v4 = QtGui.QStyleOptionViewItemV4(option) self.initStyleOption(option_v4, index) doc = self.make_text(option_v4.text) option_v4.text = "" style = QtGui.QApplication.style() style.drawControl(QtGui.QStyle.CE_ItemViewItem, option_v4, painter) painter.save() rect = style.subElementRect(QtGui.QStyle.SE_ItemViewItemText, option_v4) painter.translate(rect.topLeft()) painter.setClipRect(rect.translated(-rect.topLeft())) context = QtGui.QAbstractTextDocumentLayout.PaintContext() if option_v4.state & QtGui.QStyle.State_Selected: context.palette.setColor( QtGui.QPalette.Text, option.palette.color(QtGui.QPalette.Active, QtGui.QPalette.HighlightedText)) doc.documentLayout().draw(painter, context) painter.restore() def sizeHint(self, option, index): option_v4 = QtGui.QStyleOptionViewItemV4(option) self.initStyleOption(option_v4, index) doc = self.make_text(option_v4.text) return QtCore.QSize(doc.idealWidth(), doc.size().height()) def make_text(self, text): doc = QtGui.QTextDocument() doc.setDocumentMargin(1) f = QtGui.QTreeWidgetItem().font(0) f.setPointSize(11) doc.setDefaultFont(f) doc.setHtml(text) return doc app = QtGui.QApplication(sys.argv) tree = QtGui.QTreeWidget() tree.setHeaderHidden(True) tree.setItemDelegate(RichTextDelegate()) hoge = QtGui.QTreeWidgetItem() hoge.setText(0, '<i>hoge</i> <img src="hoge.png"/><img src="hoge.png"/>') fuga = QtGui.QTreeWidgetItem() fuga.setText(0, '<b>fuga</b> <img src="hoge.png"/><img src="hoge.png"/><img src="hoge.png"/>') piyo = QtGui.QTreeWidgetItem() piyo.setText(0, '<font color="red">piyo</font>') hoge.addChild(fuga) hoge.addChild(piyo) tree.addTopLevelItem(hoge) tree.show() sys.exit(app.exec_())
Raspberry Piでトイレにクラシック音楽を流す
人がきたら音楽を流す装置をトイレに設置しました(割と好評)
- ケースはRaspberry Piの箱に100均で買った折り紙を貼って作成
- 本体のUSBでBluetoothスピーカーを充電
必要なもの
Raspberry Piと人感センサーの接続
下記ページを確認しながらRaspberry Piと人感センサーを接続
- https://developer.microsoft.com/en-us/windows/iot/docs/pinmappingsrpi
- https://www.mpja.com/download/31227sc.pdf
対応するピン同士をジャンパーワイヤで繋ぐ
人感センサー | Raspberry Pi | |
---|---|---|
+Power | <---> | 5V PWR |
GND | <---> | GND |
High/Low Output | <---> | GPIO18 |
人感センサーで音を鳴らすプログラムの作成
import pygame, os, random, time, RPi.GPIO pygame.init() pygame.mixer.pre_init(44100, 16, 2, 1024 * 4) pygame.mixer.init() pygame.mixer.set_num_channels(8) screen = pygame.display.set_mode((320, 240)) shutdown = False clock = pygame.time.Clock() files = [] active = False last_activated = 0 pin = 18 RPi.GPIO.setmode(RPi.GPIO.BCM) RPi.GPIO.setup(pin, RPi.GPIO.IN) # 入力を検知したあとに何秒間流すか timeout = 30 # 音楽の再生 def play_random_track(): global files # 再生リストがなくなったらmp3ファイルを検索してシャッフル if not files: files = [f for f in os.listdir('./') if f.endswith('.mp3')] random.shuffle(files) # 再生リストから一番最初の音楽をとってきて鳴らす pygame.mixer.music.load(files.pop(0)) pygame.mixer.music.set_volume(1.0) pygame.mixer.music.play() # メインループ while not shutdown: # 入力フラグ active = False # OSイベント処理 for e in pygame.event.get(): # 閉じるボタンやESCキーが入力されたらプログラムを終了する if e.type == pygame.QUIT or (e.type == pygame.KEYDOWN and e.key == 27): shutdown = True break # テスト用:Enterキーで音を鳴らせるようにしておく elif e.type == pygame.KEYDOWN and e.key == 13: active = True continue # 人感センサーからの入力 if RPi.GPIO.input(pin) == RPi.GPIO.HIGH: active = True # 入力があったときの処理 if active: # 入力時間を更新する last_activated = time.time() # 再生してないときは次のトラックを再生 if not pygame.mixer.music.get_busy(): play_random_track() # 最後の入力から一定時間(timeout秒)が経過したら音楽をフェードアウトさせる if (time.time() - last_activated) > timeout: if pygame.mixer.music.get_busy(): pygame.mixer.music.fadeout(5000) pygame.display.flip() clock.tick(5) # 処理負荷を抑える(1秒間に5回ループをまわす) RPi.GPIO.cleanup() pygame.quit()
電源入れたら自動でプログラムが動くようにする
以前の記事と同じ手順で起動時にBluetoothスピーカー接続&今回用意したスクリプトを起動するように修正
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) cd otohime python3.4 otohime.py
Haskell環境構築メモ
これは自分のためのメモだから良い子は見ちゃダメ
インストール
1. Haskell PlatformからインストーラをDLして実行
適当にNext押してたら%APPDATA%\local\binにインストールされてパスが通った
stackのセットアップもすぐやったほうがいい
stack setup
2. ide-haskellのページを見ながら必要なものをインストール
バイナリ
stack install stylish-haskell stack install ghc-mod stack install hlint
Atomパッケージ
apm install language-haskell haskell-ghc-mod ide-haskell-cabal ide-haskell autocomplete-haskell
プロジェクトの作成
cd parentDir stack new projectName
依存パッケージの追加
.cabalファイルのビルドターゲットのbuild-dependesにカンマ区切りで追加して
cabal install
実行
cabal run
環境構築がもうちょっと簡単になら流行りそうなのに
Python3でSkypeにメッセージ送信
skpyを使います
準備
pip install skpy
最近のイベントからグループチャットを検索してメッセージ送信
from skpy import Skype def send(user, password, topic, message): sk = Skype(user, password) for c in sk.chats.recent(): chat = sk.chats[c] if hasattr(chat, 'topic') and chat.topic == topic: chat.sendMsg(message) break if __name__ == '__main__': send('hogehoge', 'password1234', 'group chat name', 'hello world')
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_())
参考記事