PySide:QWebView:为什么很多元素都是null?

时间:2014-06-30 10:42:19

标签: python pyqt4 pyside

为什么QWebView中的很多QWebElements都是Null?虽然它们在html中似乎完全有效。

以下是使用PySide的演示:

from PySide.QtGui import QWidget, QMainWindow, QApplication, QVBoxLayout,\
  QLineEdit, QPainter, QPen
from PySide.QtCore import QUrl, Qt
from PySide.QtWebKit import QWebView, QWebElement
import sys

class Window(QMainWindow):
  def __init__(self, parent=None):
    super(Window, self).__init__(parent)
    layout = QVBoxLayout()
    self.lineedit_search = QLineEdit()
    self.lineedit_search.editingFinished.connect(self.loadBrowser)
    self.lineedit_search.setText("http://www.imdb.com/chart/top")
    self.browser = MouseSensitiveWebView()
    self.browser.setUrl(QUrl("http://www.imdb.com/chart/top"))
    layout.addWidget(self.lineedit_search)
    layout.addWidget(self.browser)
    layout_widget = QWidget()
    layout_widget.setLayout(layout)
    self.setCentralWidget(layout_widget)

  def loadBrowser(self):
    txt = self.lineedit_search.text()
    self.browser.load(QUrl(txt))


class MouseSensitiveWebView(QWebView):
  def __init__(self, parent=None):
    super(MouseSensitiveWebView, self).__init__(parent)
    self.setMouseTracking(True)
    self._hover_rect = None
    self._hit_elem = None

  def mouseMoveEvent(self, mme):
    mouse_pos = mme.pos()
    hit_test_result = self.page().mainFrame().hitTestContent(mouse_pos)
    if hit_test_result:
      new_rect = hit_test_result.boundingRect()
      if new_rect == self._hover_rect: # don't repaint unless the hovered element changed
        return
      hit_elem = hit_test_result.element()
      if hit_elem.isNull():
        print("{0} is Null".format(hit_elem))
      else:
        print("{0} is not Null".format(hit_elem))
      self._hover_rect = new_rect  
      self._hit_elem = hit_elem
      self.repaint()
    else:
      self._hover_rect = None

  def paintEvent(self, pe):
    if not self._hover_rect:
      super(MouseSensitiveWebView, self).paintEvent(pe)
    else:
      super(MouseSensitiveWebView, self).paintEvent(pe)
      # get the current horizontal and vertical scroll bar positions
      main_frame = self.page().mainFrame()
      hor_pos, ver_pos = main_frame.scrollBarValue(Qt.Horizontal), main_frame.scrollBarValue(Qt.Vertical)
      # move the hover rect by these values
      hover_rect = self._hover_rect
      hover_rect.moveTop(hover_rect.top() - ver_pos)
      hover_rect.moveLeft(hover_rect.left() - hor_pos)
      painter = QPainter(self)
      pen = QPen(Qt.red)
      pen.setWidth(2)
      painter.setPen(pen)
      painter.drawRect(hover_rect)

if __name__ == "__main__":
  app = QApplication(sys.argv)
  main = Window()
  main.setGeometry(50, 50, 800, 600)
  main.show()
  sys.exit(app.exec_())

只需保持鼠标悬停,就会在您正在悬停的元素周围绘制一个红色方块。如果它为null,则它将记录到控制台。

您会注意到大多数可见元素实际上是Null。这使得QWebView在页面元素上运行时变得不那么有用。这也适用于PyQt4,在这方面看起来相似或事件更糟,并且获得更多Null。

1 个答案:

答案 0 :(得分:0)

首先,null元素的问题似乎最近已归档为bug

我已经做了一些解决方法,只允许选择来自内联系列的链接(<a>元素)。我得到他们的文本并在封闭的父母中搜索具有该文本的元素:

def mouseMoveEvent(self, mme):
    mouse_pos = mme.pos()
    hit_test_result = self.page().mainFrame().hitTestContent(mouse_pos)
    if hit_test_result:
      new_rect = hit_test_result.boundingRect()
      if new_rect == self._hover_rect: # don't repaint unless the hovered element changed
        return
      hit_elem = hit_test_result.element()
      if hit_elem.isNull():
        enclosing = hit_test_result.enclosingBlockElement()
        elem_text = hit_elem.linkText() # works only for <a> elements
        for subelement in enclosing.findAll('*'):
          if subelement.toPlainText() == elem_text:
            print "Found Link {}".format(subelement)
            break
        else:
          print("Element is null and not a link")
      else:
        print("{0} is not Null".format(hit_elem))
      self._hover_rect = new_rect  
      self._hit_elem = hit_elem
      self.repaint()
    else:
      self._hover_rect = None