Krita Plugin Error: Trying to build a "Gesture-to-Grid" tool and hitting a wall, its been eating me up for past 2 days

.

While using Krita, I decided to make this plugin. which will convert hand-drawn lines into the perspective grid. and Krita keeps showing me this error

Here’s my .docker-Code. Plugin is called gesture-2-grid (G2G)

from krita import *

from PyQt5.QtWidgets import *

from PyQt5.QtCore import Qt, QPointF

class G2GDocker(DockWidget):

*def* \__init_\_(*self*):

    super().\__init_\_()

    *self*.setWindowTitle("Gesture-to-Grid")

    

    main_widget = QWidget()

    layout = QVBoxLayout()

    

    \# UI Header

    *self*.lbl_info = QLabel("Draw a gesture, then click Convert.")

    *self*.lbl_info.setStyleSheet("font-size: 11px; color: #aaa;")

    *self*.lbl_info.setWordWrap(True)

    layout.addWidget(*self*.lbl_info)

    

    \# Sensitivity Slider: Low = Straight Plane, High = Vanishing Curve

    layout.addWidget(QLabel("Perspective Warp / Sensitivity:"))

    *self*.slider_curve = QSlider(Qt.Horizontal)

    *self*.slider_curve.setMinimum(0)

    *self*.slider_curve.setMaximum(100)

    *self*.slider_curve.setValue(40)

    layout.addWidget(*self*.slider_curve)

    

    \# The Action Button

    *self*.btn_convert = QPushButton("Generate Smart Grid")

    *self*.btn_convert.setStyleSheet("""

        QPushButton { background-color: #2c3e50; color: white; padding: 12px; font-weight: bold; border-radius: 4px; }

        QPushButton:hover { background-color: #34495e; }

    """)

    *self*.btn_convert.clicked.connect(*self*.run_conversion)

    layout.addWidget(*self*.btn_convert)

    

    layout.addStretch()

    main_widget.setLayout(layout)

    *self*.setWidget(main_widget)



*def* run_conversion(*self*):

    doc = Krita.instance().activeDocument()

    if not doc: return

    node = doc.activeNode()

    

    sensitivity = *self*.slider_curve.value()

    points = \[\]



    \# 1. LAYER TYPE CHECK & EXTRACTION

    if node.type() == "vectorlayer":

        points = *self*.get_vector_points(node)

    elif node.type() == "paintlayer":

        points = *self*.get_raster_points(node)

    else:

        *self*.lbl_info.setText("Error: Select a Paint or Vector layer.")

        return



    if not points or len(points) < 2:

        *self*.lbl_info.setText("Error: No drawing found on layer.")

        return



    \# 2. ADAPTIVE LOGIC BRANCHING

    if sensitivity < 35 and len(points) >= 4:

        *self*.create_perspective_plane(doc, points\[:4\])

        *self*.lbl_info.setText("Status: 4-Point Plane Generated")

    else:

        *self*.create_vanishing_curve(doc, points)

        *self*.lbl_info.setText("Status: Vanishing Curve Generated")



*def* get_vector_points(*self*, *node*):

    """Extracts precise coordinates from vector shapes."""

    shapes = *node*.shapes()

    if not shapes: return \[\]

    rect = shapes\[0\].boundingBox()

    return \[

        QPointF(rect.left(), rect.top()),

        QPointF(rect.right(), rect.top()),

        QPointF(rect.right(), rect.bottom()),

        QPointF(rect.left(), rect.bottom())

    \]



*def* get_raster_points(*self*, *node*):

    """Surface Mapping: Scans pixels to find 'Intention Points'."""

    bound = *node*.bounds()

    w, h = bound.width(), bound.height()

    if w == 0 or h == 0: return \[\]

    

    \# Bytearray fix for Krita pixelData

    pixel_data = bytearray(*node*.pixelData(bound.x(), bound.y(), w, h))

    

    pts = \[\]

    step = 10 

    

    for y in range(0, h, step):

        for x in range(0, w, step):

            \# Safely compare int to int

            if pixel_data\[(y \* w + x) \* 4 + 3\] > 20: 

                pts.append(QPointF(bound.x() + x, bound.y() + y))



    if not pts: return \[\]



    \# Find the 4 most extreme corners

    tl = min(pts, *key*=*lambda* *p*: *p*.x() + *p*.y())

    br = max(pts, *key*=*lambda* *p*: *p*.x() + *p*.y())

    tr = max(pts, *key*=*lambda* *p*: *p*.x() - *p*.y())

    bl = min(pts, *key*=*lambda* *p*: *p*.x() - *p*.y())



    return \[tl, tr, br, bl\]



*def* create_perspective_plane(*self*, *doc*, *pts*):

    """Global initialization for Krita 5.2.x."""

    \# We call the assistant creation from the main Krita instance

    assistant = Krita.instance().createPaintingAssistant("perspective")

    

    if assistant:

        assistant.setPoint(0, *pts*\[0\])

        assistant.setPoint(1, *pts*\[1\])

        assistant.setPoint(2, *pts*\[2\])

        assistant.setPoint(3, *pts*\[3\])

        

        \# Add it to the document's list

        *doc*.addAssistant(assistant)

        *doc*.waitForDone()

        

    else:

        *self*.lbl_info.setText("Error: Could not initialize 'perspective' assistant.")



*def* create_vanishing_curve(*self*, *doc*, *pts*):

    """Global initialization for Krita 5.2.x."""

    assistant = Krita.instance().createPaintingAssistant("vanishing_point")

    

    if assistant:

        assistant.setPoint(0, *pts*\[0\]) # Vanishing Point

        assistant.setPoint(1, *pts*\[-1\]) # Direction Handle

        

        *doc*.addAssistant(assistant)

        *doc*.waitForDone()

    else:

        *self*.lbl_info.setText("Error: Could not initialize 'vanishing_point' assistant.")



*def* canvasChanged(*self*, *canvas*):

    pass

Your code seems to include a lot of escape characters and formatting which makes it very hard to read. Could you please reformat it? And you also forgot to include the actual error message.

Does this even exist?

assistant = Krita.instance().createPaintingAssistant("perspective")

Where is it?

Dmm man your right. I accidentally go in other software

I retry with different method but still getting attribute error : here new code

from krita import *

from PyQt5.QtWidgets import *

from PyQt5.QtCore import Qt, QPointF

class G2GDocker(DockWidget):

def \__init_\_(self):

    super().\__init_\_()

    self.setWindowTitle("Gesture-to-Grid")

    

    main_widget = QWidget()

    layout = QVBoxLayout()

    

    \# UI Header

    self.lbl_info = QLabel("Draw a gesture, then click to spawn a Vector Grid.")

    self.lbl_info.setStyleSheet("font-size: 11px; color: #aaa;")

    self.lbl_info.setWordWrap(True)

    layout.addWidget(self.lbl_info)

    

    \# Density Slider

    layout.addWidget(QLabel("Grid Density (Divisions):"))

    self.slider_density = QSlider(Qt.Horizontal)

    self.slider_density.setMinimum(2)

    self.slider_density.setMaximum(20)

    self.slider_density.setValue(8)

    layout.addWidget(self.slider_density)

    

    \# The Action Button

    self.btn_convert = QPushButton("Generate Vector Grid")

    self.btn_convert.setStyleSheet("""

        QPushButton { background-color: #2c3e50; color: white; padding: 12px; font-weight: bold; border-radius: 4px; }

        QPushButton:hover { background-color: #34495e; }

    """)

    self.btn_convert.clicked.connect(self.run_conversion)

    layout.addWidget(self.btn_convert)

    

    layout.addStretch()

    main_widget.setLayout(layout)

    self.setWidget(main_widget)

def run_conversion(self):

    doc = Krita.instance().activeDocument()

    if not doc: return

    node = doc.activeNode()

    

    points = \[\]

    \# 1. LAYER TYPE CHECK & EXTRACTION

    if node.type() == "vectorlayer":

        points = self.get_vector_points(node)

    elif node.type() == "paintlayer":

        points = self.get_raster_points(node)

    else:

        self.lbl_info.setText("Error: Select a Paint or Vector layer.")

        return

    if not points or len(points) < 4:

        self.lbl_info.setText("Error: Needs a 4-corner shape to map.")

        return

    \# 2. GENERATE THE VECTOR GRID

    self.create_vector_grid(doc, points)

    self.lbl_info.setText("Status: Vector Grid Generated Successfully!")

def get_vector_points(self, node):

    """Extracts precise coordinates from vector shapes."""

    shapes = node.shapes()

    if not shapes: return \[\]

    rect = shapes\[0\].boundingBox()

    return \[

        QPointF(rect.left(), rect.top()),

        QPointF(rect.right(), rect.top()),

        QPointF(rect.right(), rect.bottom()),

        QPointF(rect.left(), rect.bottom())

    \]

def get_raster_points(self, node):

    """Scans pixels to find the 4 extreme corners of your sketch."""

    bound = node.bounds()

    w, h = bound.width(), bound.height()

    if w == 0 or h == 0: return \[\]

    

    \# Safely extract pixels as integers

    pixel_data = bytearray(node.pixelData(bound.x(), bound.y(), w, h))

    pts = \[\]

    step = 10 

    

    for y in range(0, h, step):

        for x in range(0, w, step):

            \# Alpha check

            if pixel_data\[(y \* w + x) \* 4 + 3\] > 20: 

                pts.append(QPointF(bound.x() + x, bound.y() + y))

    if len(pts) < 4: return \[\]

    \# Find the 4 diagonal extremes

    tl = min(pts, key=lambda p: p.x() + p.y())

    br = max(pts, key=lambda p: p.x() + p.y())

    tr = max(pts, key=lambda p: p.x() - p.y())

    bl = min(pts, key=lambda p: p.x() - p.y())

    return \[tl, tr, br, bl\]

def create_vector_grid(self, doc, pts):

    """Draws a mathematical wireframe grid based on the 4 corners."""

    density = self.slider_density.value()

    

    \# Create a brand new Vector Layer

    root = doc.rootNode()

    grid_layer = doc.createVectorLayer("Gesture Grid")

    root.addChildNode(grid_layer, None)

    

    \# Start building the SVG string

    svg = '<svg xmlns="http://www.w3.org/2000/svg">'

    svg += '<path d="'

    

    def lerp(p1, p2, t):

        """Linear interpolation between two points."""

        return QPointF(p1.x() + (p2.x() - p1.x()) \* t, p1.y() + (p2.y() - p1.y()) \* t)

    

    \# Generate the subdividing lines

    for i in range(1, density):

        t = i / float(density)

        

        \# Vertical-ish lines

        top_p = lerp(pts\[0\], pts\[1\], t)

        bot_p = lerp(pts\[3\], pts\[2\], t)

        svg += f'M {top_p.x()},{top_p.y()} L {bot_p.x()},{bot_p.y()} '

        

        \# Horizontal-ish lines

        left_p = lerp(pts\[0\], pts\[3\], t)

        right_p = lerp(pts\[1\], pts\[2\], t)

        svg += f'M {left_p.x()},{left_p.y()} L {right_p.x()},{right_p.y()} '

        

    \# Draw the outer boundary box

    svg += f'M {pts\[0\].x()},{pts\[0\].y()} L {pts\[1\].x()},{pts\[1\].y()} '

    svg += f'L {pts\[2\].x()},{pts\[2\].y()} L {pts\[3\].x()},{pts\[3\].y()} Z'

    

    \# Close the SVG path with a bright red stroke

    svg += '" stroke="#ff0044" stroke-width="2" fill="none" opacity="0.6"/>'

    svg += '</svg>'

    

    \# Push the SVG to Krita and refresh the screen

grid_layer.addShapesFromSvg(svg)

    doc.refreshProjection()

    doc.waitForDone()

def canvasChanged(self, canvas):

    pass

First, you need to output code properly without the escapes and into the code block.

So like this:

```
code goes here
```

Second, give the exact error you get too inside a code block

This error was showing

I don’t undrstand what you mean by outputting code proplerly

  1. Your error still says “createPaintingAssistant” so you didn’t remove that.
  2. You see how your code is broken up instead of all being in the box? You need to use ``` to put it in code block. You also see how your code has \ those are escape characters most of which should not be there.

OK Thanks I will surely update

Are you by any chance using some kind of AI coding assistant to help with the coding?

1 Like

Yeah, in some parts. But I still don’t trust over AI coding that much

I change the whole process and start again. This time I decided to make an OpenCV engine. But still even before Krita starts, it’s showing this error, and even in the Python plugin manager, the plugin is active but not showing anywhere.

here the GitHub link: GitHub - P00A/Krita-plugin-Gesture_2_Grid: Convert hand-drawn lines into perspective grids · GitHub , kindly tell the error my brain is getting eaten inside out..

Errors

image

I think she probably means that your AI assistant is maybe hallucinating functions and members that do not exist.

QLabel is not defined means you probably forgot to import it from the Qt library.

let me try

qt is new to me

Even after this long. I can’t make it alone. Someone kindly help.

Now showing this error

and here this update link of github page : GitHub - P00A/Krita-plugin-Gesture_2_Grid: Convert hand-drawn lines into perspective grids · GitHub

First of all, does your code actually work as expected? Did you test it in Scripter before creating the plugin? You should make sure the code works before turning it into a plugin.

Just in case, here’s a link to Scripting School.

Sure yeah , all codes are runing without showing any error

Please try adding the following to the class GestureToGrid(DockWidget) section in gesture_2_grid.py.

#class GestureToGrid(DockWidget):#


    def canvasChanged(self, canvas):#add
        pass