初心者でも絶対出来る自作ブラウザ[Python]第6章 ボタンの動作作成
今日はブラウザを1から作ってみたいシリーズの第6弾のボタンの動作作成です
今回も初心者でも絶対できるように細かく説明していきます
このシリーズを読んでいけば以下のことができるようになります
- 仕様検討
- Pythonの環境構築構築
- Pythonのライブラリの導入方法
- Pythonでの開発
- 自作ブラウザの表示
- ブラウザのカスタマイズ ←この記事
前回の記事ではブラウザのGUIをデザインしてボタンなどを作成しました
前回はデザインのみでしたので、作成したボタンを押しても何も起きない状態でした
今回はボタンを押した時にちゃんと動作するように実装していきます
シグナルとスロットについて
Qtでは独自のシグナルとスロットという仕組みを用いてイベント処理を行います
シグナルがユーザがマウスやキーボードを使用して実行する動作を定義したものです
スロットがシグナルが発生した時に実行したい処理内容となります
このシグナルとスロットを組み合わせることをコネクトと呼びます
例えば、「戻るボタンを押す」と「1つ前のページに戻る」動作を行う場合 シグナルが「戻るボタンを押す」で スロットが「1つ前のページに戻る」となりますシグナルとスロットについて詳しく知りたい方は以下のQtのサイトをご覧ください
https://doc.qt.io/qt-5/signalsandslots.html
Qt Designerでのシグナルとスロット作成
Qt Designerを実行して前回のUIを開きます
画面ジョブのシグナル/スロットを編集ボタンを押します
シグナルとスロットの編集モードになりますので設定します
設定方法はユーザが操作するアイテムをクリックした状態で、処理を実行するアイテム上にマウスを移動させて離します
例えば戻るボタンを押して1つ前のページに戻る際には
ユーザが操作するのは「戻るボタン」で、処理を実行するのはwebEngineViewです
戻るボタンをwebEngineViewにドラッグ&ドロップ するようなイメージです
ドラッグ&ドロップ すると以下の画面が開きますので、ここでシグナルをスロットを選びます
標準でよく使用するものが用意されています
左がシグナルとなっており、ここではボタンのクリック(clicked())を選択します
右がスロットとなっており、ここでは戻る(back())を選択します
戻る、進む、更新ボタンのclicked()にそれぞれback()、forward()、reload()を設定します
設定が完了したら、前回同様.uiファイルから.pyファイルに変換してください
今回シグナルとスロットを追加したことにより以下の行が追加されています
アイテム.シグナル.connect(スロット)という形で記述されます
self.pushButton_2.clicked.connect(self.webEngineView.forward)
self.pushButton.clicked.connect(self.webEngineView.back)
self.pushButton_3.clicked.connect(self.webEngineView.reload)
ソース上でのスロット作成
上のソースコードに自作のスロットを追加したbrowser2UI.pyの全体が以下となります
前回同様、初期ページ設定の以下もお忘れなく!!
initurl = 'https://www.google.co.jp’
self.webEngineView.setUrl(QtCore.QUrl(initurl))
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'browser2.ui'
#
# Created by: PyQt5 UI code generator 5.9.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout.addWidget(self.pushButton)
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setObjectName("pushButton_2")
self.horizontalLayout.addWidget(self.pushButton_2)
self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_3.setObjectName("pushButton_3")
self.horizontalLayout.addWidget(self.pushButton_3)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.pushButton_4 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_4.setObjectName("pushButton_4")
self.horizontalLayout.addWidget(self.pushButton_4)
self.verticalLayout.addLayout(self.horizontalLayout)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setObjectName("label")
self.horizontalLayout_2.addWidget(self.label)
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setObjectName("lineEdit")
self.horizontalLayout_2.addWidget(self.lineEdit)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.webEngineView = QtWebEngineWidgets.QWebEngineView(self.centralwidget)
initurl = 'https://www.google.co.jp'
self.webEngineView.setUrl(QtCore.QUrl(initurl))
self.webEngineView.setObjectName("webEngineView")
self.verticalLayout.addWidget(self.webEngineView)
self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 17))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.pushButton_2.clicked.connect(self.webEngineView.forward)
self.pushButton.clicked.connect(self.webEngineView.back)
self.pushButton_3.clicked.connect(self.webEngineView.reload)
self.lineEdit.returnPressed.connect(MainWindow.webPageUpdate)
self.webEngineView.urlChanged['QUrl'].connect(MainWindow.urlLineSet)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "pyQtBrowser"))
self.pushButton.setText(_translate("MainWindow", "戻る"))
self.pushButton_2.setText(_translate("MainWindow", "進む"))
self.pushButton_3.setText(_translate("MainWindow", "更新"))
self.pushButton_4.setText(_translate("MainWindow", "お気に入り"))
self.label.setText(_translate("MainWindow", "URL:"))
from PyQt5 import QtWebEngineWidgets
追加したのは以下の2行でそれぞれ
lineEditでエンターキーを押された際にMainWindow.webPageUpdate()を
webEngineViewでURLが変更された際にMainWindow.urlLineSet()を
呼び出す設定です
呼び出す関数についてはbrowser2.pyにて実装します
self.lineEdit.returnPressed.connect(MainWindow.webPageUpdate)
self.webEngineView.urlChanged['QUrl'].connect(MainWindow.urlLineSet)
GUIを呼び出す方のbrowser2.pyは以下となります
import sys
from PyQt5 import QtWidgets
from browser3Ui import Ui_MainWindow
from PyQt5.QtCore import QUrl
class browserUI(QtWidgets.QMainWindow):
def __init__(self,parent=None):
super(browserUI, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
def webPageUpdate(self):
self.ui.webEngineView.setUrl(QUrl(self.ui.lineEdit.text()))
def urlLineSet(self, QUrl):
self.ui.lineEdit.setText(self.ui.webEngineView.url().url())
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = browserUI()
window.show()
sys.exit(app.exec_())
def webPageUpdate(self):
self.ui.webEngineView.setUrl(QUrl(self.ui.lineEdit.text()))
webPageUpdate()ではlineEditに入力されたURLをwebEngineViewに設定する処理を行っています
def urlLineSet(self, QUrl):
self.ui.lineEdit.setText(self.ui.webEngineView.url().url())
urlLineSet()ではwebEngineViewで変更されたURLをlineEditにセットする処理を行っています
実行
前回同様browser2.pyを実行します
起動した時にURL:に現在のURLが表示されているのが確認できます
検索を実行していみると、URL:の表示が変わるのが確認できます
戻るや進むボタンでページを行ったり来たりできます
次にURLにこのブログのトップページのURLを入力してエンターキーを押します
見事トップページが表示されました
まとめ
今回はGUIのボタン等を押した際の処理を実装しました
Qtのシグナルとスロットを使用することで、ユーザの操作と処理の実行を簡単に結びつけることができました
自作のスロットを使用して様々な処理を追加することでブラウザの完成度をアップさせていきましょう
質問や相談あればドシドシご連絡ください!!
こんなの作ってみたい等の依頼も募集してますよ~
ディスカッション
コメント一覧
ショウさんの自作ブラウザ[Python]の記事を読ませて頂き、タイトルの通り私にも出来ました!ありがとうございます。
初めて扱う言語やツールでしたが、とても分かりやすい説明で本当に助かりました!ありがとうございます。
質問をよろしいでしょうか?
別ウィンドウで開く動作(HTMLタグでいうと「target=”_blank”」)の実装方法がわかりません。何かヒントを頂ければ幸いです。何卒宜しくお願いいたします。
ブログをご覧いただきありがとうございます。
ブラウザを作ってみることができたようで、良かったです。
早速質問についてですが、別ウィンドウで開く動作ということで、実装方法は色々考えられると想いますが、何かしらのシグナルで繋いだスロットにてbrowserUI()を作成してshowすればよいかと思います。
その際、モードレス(呼び出した画面がロックされない)で呼べば、元の画面も操作できます。
こちらでも、時間がある時に試してみようかと思います
ショウさん、早速のご回答感謝いたします。
当方PythonやQtは初めてなので手探り状態でやっております。
もし、サンプルコード的なものがございましたらご教授頂けたら幸いです。
本当にありがとうございます。
もう1点質問があります。
この自作ブラウザでPDFファイルを表示することは可能なのでしょうか?
何度も申し訳ありません。
ご教授頂けましたら幸いです。
よろしくお願いいたします。
現状ではPDFの表示には対応しておりません。
技術的には可能だと思うので、試せたらまたブログに書こうと思います
ご回答ありがとうございます。
遅くなりましたがPDFの表示ができましたので、記事UPしました
参考にしていただけたらと思います。
ありがとうございます。
当方の環境で試したところ下記のエラーが出て起動しませんでした。
AttributeError: type object ‘QWebEngineSettings’ has no attribute ‘PdfViewerEnabled’
何か不足しているものがあるのでしょうか?
いろいろ調べていますが未だ解決しません。
お手数をおかけして申し訳ありません。ご教授頂ければ幸いです。
よろしくお願いいたします。
PyQt5とPyQtWebEngineのバージョンは5.13以上となってますか?
はい、ご教授頂いた通りpip listで確認しました。
両方とも5.13.2です。
また、開発環境も前回(10月)質問した時のものは削除して、今回全て再構築しました。
エラーメッセージとしては、PdfViewerEnabledがないよと言うものなのですが、他の要因が特に思い当たりません。
原因を探るため、実行時のコマンドプロンプトのキャプチャなどは見せてもらうことは可能ですか?
ありがとうございます。
はい、もちろん可能です。
キャプチャ等はどちらに送ればよろしいでしょうか?
sho1009case@gmail.com
こちらまでお願いします
早速のアドバイス、ありがとうございました。
出来ました!本当に助かりました。
PDF表示の実装及び記事のアップありがとうございます!
大変助かります。また実際におこなってみてご連絡いたします。
取り急ぎお礼まで。
ショウさん、はじめまして。自作ブラウザの記事を楽しく読ませてもらっています。
さっそく質問なのですが、自作ブラウザで表示させたページ内に書かれている文章内の検索や指定した文字だけ色を変える、フォントを変えるなどの事は可能でしょうか?文書を読む前に気になるワードにハイライトをつけられたら良いなと思いまして。
お問い合わせありがとうございます。
調べてみたのですが、検索や文字のハイライト等は簡単にはできそうにありません。
実装できましたらブログに書きますので、少々お待ちください
ショウさん初めまして。記事を読ませてもらいました。browser2.pyを実行すると、「ModuleNotFoundError: No module named ‘browser3Ui’」というエラーが出てしまいます。
解決方法を教えてください。お願いします。
すいません、解決しました。