初心者でも絶対出来る自作ブラウザ[Python]第6章 ボタンの動作作成

2021年5月12日

今日はブラウザを1から作ってみたいシリーズの第6弾のボタンの動作作成です
今回も初心者でも絶対できるように細かく説明していきます

このシリーズを読んでいけば以下のことができるようになります

  • 仕様検討
  • Pythonの環境構築構築
  • Pythonのライブラリの導入方法
  • Pythonでの開発
  • 自作ブラウザの表示
  • ブラウザのカスタマイズ ←この記事

前回の記事ではブラウザのGUIをデザインしてボタンなどを作成しました

前回はデザインのみでしたので、作成したボタンを押しても何も起きない状態でした
今回はボタンを押した時にちゃんと動作するように実装していきます

シグナルとスロットについて

Qtでは独自のシグナルとスロットという仕組みを用いてイベント処理を行います

シグナルがユーザがマウスやキーボードを使用して実行する動作を定義したものです

スロットがシグナルが発生した時に実行したい処理内容となります

このシグナルとスロットを組み合わせることをコネクトと呼びます

例えば、「戻るボタンを押す」と「1つ前のページに戻る」動作を行う場合 シグナルが「戻るボタンを押す」で スロットが「1つ前のページに戻る」となります

シグナルとスロットについて詳しく知りたい方は以下のQtのサイトをご覧ください

https://doc.qt.io/qt-5/signalsandslots.html

Qt Designerでのシグナルとスロット作成

Qt Designerを実行して前回のUIを開きます

画面ジョブのシグナル/スロットを編集ボタンを押します

前回作成したGUI
qtDesigner

シグナルとスロットの編集モードになりますので設定します
設定方法はユーザが操作するアイテムをクリックした状態で、処理を実行するアイテム上にマウスを移動させて離します

例えば戻るボタンを押して1つ前のページに戻る際には
ユーザが操作するのは「戻るボタン」で、処理を実行するのはwebEngineViewです
戻るボタンをwebEngineViewにドラッグ&ドロップ するようなイメージです

シグナルとスロットの編集画面
qtDesigner

ドラッグ&ドロップ すると以下の画面が開きますので、ここでシグナルをスロットを選びます

標準でよく使用するものが用意されています
左がシグナルとなっており、ここではボタンのクリック(clicked())を選択します
右がスロットとなっており、ここでは戻る(back())を選択します

戻るボタンの設定
qtDesigner

戻る、進む、更新ボタンの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が表示されているのが確認できます

実行画面(グーグル)
qtDesigner2

検索を実行していみると、URL:の表示が変わるのが確認できます

検索画面(Python)
qtDesigner2

戻るや進むボタンでページを行ったり来たりできます

Pythonページを開く
qtDesigner2

次にURLにこのブログのトップページのURLを入力してエンターキーを押します

URL入力画面
qtDesigner2

見事トップページが表示されました

URL入力での画面遷移
qtDesigner2

まとめ

今回はGUIのボタン等を押した際の処理を実装しました
Qtのシグナルとスロットを使用することで、ユーザの操作と処理の実行を簡単に結びつけることができました

自作のスロットを使用して様々な処理を追加することでブラウザの完成度をアップさせていきましょう

質問や相談あればドシドシご連絡ください!!
こんなの作ってみたい等の依頼も募集してますよ~