2012/09/30(日) [n年前の日記]
#1 [python] QWebViewを勉強中
 PyQt勉強中。Webページを表示できる QwebView について色々調べてるところ。
スクロールバーを制御できなくて悩んでたけど。どうやら、QWebView.page().mainFrame() がページ読み込み終了していない状態でスクロールバーを弄ろうとしていたのが原因だったらしい。mainFrame() 、というか QWebFrame() は、ページ読み込み終了時に loadFinished() を発生させるので、そこでフラグを立てて、そのフラグを見ながらスクロールバーを制御するようにしてみたり。
また、編集ウインドウ(QTextEdit)内でカーソル位置が変わった際に、cursorPositionChanged() が発生するので、その中でもスクロールバーを制御するようにした。
とりあえず、分かった範囲でメモ。
ソースは以下のような感じに。
 スクロールバーを制御できなくて悩んでたけど。どうやら、QWebView.page().mainFrame() がページ読み込み終了していない状態でスクロールバーを弄ろうとしていたのが原因だったらしい。mainFrame() 、というか QWebFrame() は、ページ読み込み終了時に loadFinished() を発生させるので、そこでフラグを立てて、そのフラグを見ながらスクロールバーを制御するようにしてみたり。
また、編集ウインドウ(QTextEdit)内でカーソル位置が変わった際に、cursorPositionChanged() が発生するので、その中でもスクロールバーを制御するようにした。
とりあえず、分かった範囲でメモ。
- スクロールバーを制御したい。 → QWebView.page().mainFrame() からアクセスする。
 - スクロールバーに指定できる最小値、最大値を知りたい。 → QWebFrame.scrollBarMinimum(種類)、QWebFrame.scrollBarMaximum(種類) が使える。
 - 種類に、QtCore.Qt.Vertical を指定すると垂直バーに対する処理に、QtCore.Qt.Horizontal を指定すると水平バーに対する処理になる。
 - スクロールバーの値を変更したい。 → QWebFrame.setScrollBarValue(種類, 値) が使える。
 - Webページのサイズが変わった時に処理を行いたい。 → QwebFrame.contentsSizeChanged を使う。
 - Webページの読み込みが終わった時に処理を行いたい。 → QWebFrame.loadFinished を使う。
 - 編集ウインドウ(QTextEdit)内の全行数を知りたい。 → QTextEdit.document().blockCount() を使う。
 - 編集ウインドウ(QTextEdit)内の、カーソル位置が何行目かを知りたい。 → QTextEdit.textCursor().blockNumber() を使う。
 
ソースは以下のような感じに。
        # 編集ウインドウ内でカーソル位置が変更された際に呼ばれる処理を設定
        self.ui.editor_window.cursorPositionChanged.connect(self.chg_position)
        # QWebView内サイズが変更された際に呼ばれる処理を指定を設定
        self.mainframe = self.ui.my_webview.page().mainFrame()
        self.mainframe.contentsSizeChanged.connect(self.chg_contents_size)
        # QWebViewで読み込み終了時に呼ばれる処理を設定
        self.mainframe.loadFinished.connect(self.load_finished)
    def chg_position(self):
        """編集ウインドウ内でカーソル位置が変更された時に呼ばれる処理"""
        if  self.load_success:
            self.textEdit = self.ui.editor_window
            c = self.textEdit.textCursor()
            bcnt = self.textEdit.document().blockCount()    # 文書行数
            ncnt = self.textEdit.textCursor().blockNumber() # 現在の行位置
            # 編集ウインドウ内カーソル位置によってスクロールバーの値を変更
            if c.atEnd():
                # ページ文末までスクロール
                self.scroll_page_end()
                self.scrl_per = 100
            elif c.atStart():
                # ページ文頭までスクロール
                self.scroll_page_start()
                self.scrl_per = 0
            else:
                # 大味の割合でスクロール
                self.scrl_per = int(ncnt * 100 / (bcnt -1))
                self.scroll_page_per(self.scrl_per)
    def chg_contents_size(self):
        """QWebView内のサイズが変更された際に呼ばれる処理"""
        # ページサイズを取得する
        c_size = self.ui.my_webview.page().mainFrame().contentsSize()
        self.mainframe_w = c_size.width()
        self.mainframe_h = c_size.height()
        ## print "frame w,h=%d,%d" % (self.mainframe_w, self.mainframe_h)
        if False:
            self.mainframe = self.ui.my_webview.page().mainFrame()
            self.mainframe_vw = self.mainframe.geometry().width()
            self.mainframe_vh = self.mainframe.geometry().height()
            print "view w,h=%d,%d" % (self.mainframe_w, self.mainframe_h)
    def load_finished(self):
        """QwebViewのロード終了時に呼ばれる処理"""
        self.load_success = True
        # 編集ウインドウ内カーソル位置によって、
        # スクロールバーの値を変更する
        c = self.ui.editor_window.textCursor()
        if c.atEnd():
            # ページ文末までスクロール
            self.scroll_page_end()
        elif c.atStart():
            # ページ文頭までスクロール
            self.scroll_page_start()
    def scroll_page_start(self):
        """QWebViewに対してページ文頭までスクロール"""
        self.mainframe = self.ui.my_webview.page().mainFrame()
        orient = QtCore.Qt.Vertical
        svmin = self.mainframe.scrollBarMinimum(orient)
        svmax = self.mainframe.scrollBarMaximum(orient)
        self.mainframe.setScrollBarValue(orient, svmin)
    def scroll_page_end(self):
        """QWebViewに対してページ文末までスクロール"""
        self.mainframe = self.ui.my_webview.page().mainFrame()
        orient = QtCore.Qt.Vertical
        svmin = self.mainframe.scrollBarMinimum(orient)
        svmax = self.mainframe.scrollBarMaximum(orient)
        self.mainframe.setScrollBarValue(orient, svmax)
    def scroll_page_per(self, per):
        """QWebViewに対して指定の割合でスクロール。
        割合は、0〜100 を与える。"""
        self.mainframe = self.ui.my_webview.page().mainFrame()
        orient = QtCore.Qt.Vertical
        svmin = self.mainframe.scrollBarMinimum(orient)
        svmax = self.mainframe.scrollBarMaximum(orient)
        v = int(((svmax - svmin) * per / 100) + svmin)
        self.mainframe.setScrollBarValue(orient, v)
◎ 全然関係ないけど。 :
どうもここ数日、苦行のADVゲームをやり続けている気がする…。しかも8bitPC時代の、コマンド入力型のADVゲーム。この単語は通るのか、通らないのか、通るとしたら何が出てくるのか、みたいなことを延々やってるような。
英語がすらすら読める人なら、PyQtはドキュメントも豊富、公式のドキュメントを眺めるだけで何ができるか分かる、と言い切れるのだろうけど。英語赤点の自分にとっては、ドキュメントは皆無に等しい。ただ、コマンド一覧だけはちゃんとある、みたいな状態。
別の何かで作れば、日本語で書かれた解説文書もたくさんあったりして、サクサク進んだのだろうなあ。でも、コンパイルしてバイナリを作るタイプの何かでは、作る気が起きないし。クローズドソースでバイナリだけ公開されているアプリがバグだらけで辟易したから、Python + PyQt4 で書けないかなと夢想しちゃったわけで…。スクリプトなら、誰でもソース見て「ここがマズいんじゃね?」と指摘できる可能性がありそうだよなと。
しかし、考えてみたら、ブラウザ + JavaScript で動く海外製 Markdownエディタのマズいところを少し修正、のほうが早かったんじゃ…?
英語がすらすら読める人なら、PyQtはドキュメントも豊富、公式のドキュメントを眺めるだけで何ができるか分かる、と言い切れるのだろうけど。英語赤点の自分にとっては、ドキュメントは皆無に等しい。ただ、コマンド一覧だけはちゃんとある、みたいな状態。
別の何かで作れば、日本語で書かれた解説文書もたくさんあったりして、サクサク進んだのだろうなあ。でも、コンパイルしてバイナリを作るタイプの何かでは、作る気が起きないし。クローズドソースでバイナリだけ公開されているアプリがバグだらけで辟易したから、Python + PyQt4 で書けないかなと夢想しちゃったわけで…。スクリプトなら、誰でもソース見て「ここがマズいんじゃね?」と指摘できる可能性がありそうだよなと。
しかし、考えてみたら、ブラウザ + JavaScript で動く海外製 Markdownエディタのマズいところを少し修正、のほうが早かったんじゃ…?
[   ツッコむ ]
以上、1 日分です。