Найти - Пользователи
Полная версия: PyQT4 | Кликабельные интернет-ссылки в многострочном поле QTextEdit или QTextBrowser
Начало » GUI » PyQT4 | Кликабельные интернет-ссылки в многострочном поле QTextEdit или QTextBrowser
1
Kyrym
Есть у меня многострочное поле, хочу в нём делать интернет-ссылки. Т.е. кликнул по ссылке, запустился браузер по умолчанию, а в нём открылась страница. Вроде как для этих целей должен подходить QTextBrowser, однако, после нажатия на ссылку, выведенный в поле текст пропадает. Меня это не устраивает. Мне нужно поведение типа, как в ворде или аналогичных редакторах, желательно без клавиши Ctrl.
Есть у меня набросок программы.
 # Python 3
# -*- coding: utf-8 -*-
import sys, webbrowser
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import (QWidget, qApp, QAction, QApplication, QHBoxLayout, QVBoxLayout,
                             QGridLayout, QLabel, QLineEdit, QTextEdit, QPushButton, QComboBox,
                             QCheckBox, QRadioButton, QFrame, QScrollArea, QTabWidget, QSizePolicy,
                             QGroupBox, QFileDialog,QTextBrowser)
from PyQt4.QtGui import QIcon, QPixmap, QPalette, QTextCursor
from PyQt4.QtCore import QSize
# ЦВЕТА ПОЛЕЙ
sss_vivod = ("background-color: #456173; color: #f2f2f0; font: 14pt 'Courier New'")
# ГРАФИКА
class Window(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.resize(200, 200) # шир / выс окна
        self.setWindowTitle('Заголовок') # Заголовок
        
        # БЛОК РАЗМЕТКИ
        #grid_os = QGridLayout()
        vbox = QVBoxLayout()
        # ---
        self.pole = QTextBrowser()
        self.pole.anchorClicked['QUrl'].connect(self.linkClicked)
        vbox.addWidget(self.pole)
        # ---
        self.setLayout(vbox)
        # --- ---
        Window.on_start(self)
    # ЛОГИКА
    
    def on_start(self):
        text = 'Некий текст<br>\
<a href="http://google.com">TEST LINK</a><br>\
Ещё текст'        
        self.pole.setText(text)
        '''for i in data:
            self.pole.append(str(i))'''
        self.pole.moveCursor(QtGui.QTextCursor.Start)
    def linkClicked(self, url):
        print(url.toString())
        webbrowser.open(url.toString())
# КОНЕЦ
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()   
    window.show()
    sys.exit(app.exec_())
    
PEHDOM
Kyrym ну елки-палки, вы опять напрочь игнорируете документацию?
http://doc.crossplatform.ru/qt/4.7.x/qtextbrowser.html#anchorClicked
там же английским по белому написано:
Note that the browser will automatically handle navigation to the location specified by link unless the openLinks property is set to false or you call setSource() in a slot connected. This mechanism is used to override the default navigation features of the browser.
Перевод:
Обратите внимание, что браузер автоматически обрабатывает навигацию в местоположении, указанном ссылкой, если для свойства openLinks не установлено значение false или вы вызываете setSource () в подключенном слоте. Этот механизм используется для переопределения навигационных функций по умолчанию браузера.
Тоесть простыми словами, щелкая по ссылке в QTextBrowser кутекстбраузер переходит по ссылке, или по крайней мере пытается это сделать, соответственно очищает поле, для отображения новой страницы.
Отключается такое поведение через self.pole.setOpenLinks(False)
Kyrym
Вообще-то документацию я читал, но как-то даже с переводом сложно понять, что setOpenLinks(False) делает то, что мне нужно.
Ладно, теперь работает.

Kyrym
Хм. обнаружил неведому ошибку.

В тестовой программе 1 поле-браузер и три кнопки, каждая из которых вставляет в поле текст. Первый текст с ссылкой, остальные без оной.
Запускаем программу, кликаем по второй кнопке, видим беленький текст (так и должно быть). Далее кликаем по первой кнопке, видим обычный белый текст + синюю ссылку. Кликаем по ссылке, открывается браузер, после чего переходим обратно в окно программы. Теперь , если мы нажмём на кнопку 2 или 3, то увидим, что наш белый обычный текст превратился в гиперссылку, причём содержание текста будет соответствовать тексту, вставляемому кнопками 2 и 3, а ссылка будет из первой кнопки (т.е. при нажатии на текст 2 или 3, мы перейдём по ссылке 1). Фиксируем ошибку.
Далее. Если мы снова нажмём кнопку 1, то увидим правильный текст по кнопке 1. Жмём кнопки 2 или 3, и видим, что текст стал снова обычным белым, гиперссылка исчезла.

Вопрос в том, как пофиксить ошибку и откуда она вообще берётся? Ведь текст вставляется через setText, т.е. затирая предыдущий.
Пока что, я решил вопрос, добавив в функцию def linkClicked(self, url): последней строчкой self.on_click_1(), но решение мне не очень нравится.
Примечально, что данное решение не работает без строчки:
 self.pole_vivod.moveCursor(QtGui.QTextCursor.Start)
Весь код:
 # Python 3
# -*- coding: utf-8 -*-
import sys, webbrowser
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import (QWidget, qApp, QAction, QApplication, QHBoxLayout, QVBoxLayout,
                             QGridLayout, QLabel, QLineEdit, QTextEdit, QPushButton, QComboBox,
                             QCheckBox, QRadioButton, QFrame, QScrollArea, QTabWidget, QSizePolicy,
                             QGroupBox, QFileDialog, QTextBrowser)
from PyQt4.QtGui import QIcon, QPixmap, QPalette, QTextCursor
from PyQt4.QtCore import QSize
# ЦВЕТА ПОЛЕЙ
sss_vivod = ("color: #f2f2f0; font: 14pt 'Courier New'")
# ГРАФИКА
class Window(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.resize(250, 200) # шир / выс окна
        self.setWindowTitle('Заголовок') # Заголовок
        # БЛОК РАЗМЕТКИ
        grid_os = QGridLayout()
        
        # ---
        self.pole_vivod = QTextBrowser()
        self.pole_vivod.setStyleSheet(sss_vivod)
        self.pole_vivod.anchorClicked['QUrl'].connect(self.linkClicked)
        self.pole_vivod.setOpenLinks(False) # запрет удаления ссылки
        grid_os.addWidget(self.pole_vivod, 0,0)
        # --- ---
        vbox = QVBoxLayout()
        grid_os.addLayout(vbox, 0,1)
        # ---
        self.btn_1 = QPushButton('Текс 1')
        self.btn_1.clicked.connect(self.on_click_1)
        vbox.addWidget(self.btn_1)
        # ---
        self.btn_2 = QPushButton('Текс 2')
        self.btn_2.clicked.connect(self.on_click_2)
        vbox.addWidget(self.btn_2)
        # ---
        self.btn_3 = QPushButton('Текс 3')
        self.btn_3.clicked.connect(self.on_click_3)
        vbox.addWidget(self.btn_3)
        vbox.addStretch()
        # ---
        self.setLayout(grid_os)
        # --- ---
    # ЛОГИКА
    
    def on_click_1(self):
        text = 'Некий текст<br>\
<a href="http://python.su/forum/18/">TEST LINK</a><br>\
Ещё текст'       
        self.pole_vivod.setText(text)
        self.pole_vivod.moveCursor(QtGui.QTextCursor.Start)
    def on_click_2(self):
        text = 'Текст второй кнопки'       
        self.pole_vivod.setText(text)
        self.pole_vivod.moveCursor(QtGui.QTextCursor.Start)
    def on_click_3(self):
        text = 'Текст третьей кнопки'
        self.pole_vivod.setText(text)
        self.pole_vivod.moveCursor(QtGui.QTextCursor.Start)
    def linkClicked(self, url):
        webbrowser.open(url.toString())
# КОНЕЦ
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    window = Window()   
    window.show()
    sys.exit(app.exec_())
    
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB