I want to draw 16*64 matrix, each one containing a:
Microsoft.VisualBasic.PowerPacks.OvalShape.
I used this:
List<Microsoft.VisualBasic.PowerPacks.OvalShape> ovalShape =
new List<Microsoft.VisualBasic.PowerPacks.OvalShape>();
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 64; j++)
{
OvalShape ovl = new OvalShape();
ovl.Width = 20;
ovl.Height = 20;
ovl.FillStyle = FillStyle.Solid;
ovl.FillColor = Color.Green;
ovalShape.Add(ovl);
}
}
How can I show it in the Window?
Creating a separate container for each shape is not required. Also you can skip the additional container list for the shapes. So you could use this very compact code.
var ovalShapes = new Microsoft.VisualBasic.PowerPacks.ShapeContainer()
{
Dock = DockStyle.Fill,
Margin = new Padding(0),
Padding = new Padding(0),
};
for (int i = 0; i < 16; i++)
for (int j = 0; j < 64; j++)
ovalShapes.Shapes.Add(
new Microsoft.VisualBasic.PowerPacks.OvalShape()
{
Width = 20,
Height = 20,
FillStyle = Microsoft.VisualBasic.PowerPacks.FillStyle.Solid,
FillColor = Color.Green,
Location = new Point(20 * i, 20 * j),
});
this.Controls.Add(ovalShapes);
From MSDN:
An OvalShape control cannot be displayed directly on a form or
container control; it must be contained in a ShapeContainer object.
After you initialize an OvalShape, you will have to set its Parent
property either to an existing ShapeContainer or to a new instance of
ShapeContainer.
Try to set Location and add your controls to the Form:
List<Microsoft.VisualBasic.PowerPacks.OvalShape> ovalShape = new List<Microsoft.VisualBasic.PowerPacks.OvalShape>();
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 64; j++)
{
OvalShape ovl = new OvalShape();
ovl.Width = 20;
ovl.Height = 20;
ovl.FillStyle = FillStyle.Solid;
ovl.FillColor = Color.Green;
ovl.Location = new Point(ovl.Width*i, ovl.Height*j);
ovalShape.Add(ovl);
}
}
foreach(OvalShape os in ovalShape)
{
Microsoft.VisualBasic.PowerPacks.ShapeContainer shapeContainer = new Microsoft.VisualBasic.PowerPacks.ShapeContainer();
Control c = new Control();
shapeContainer.Parent = c;
os.Parent = shapeContainer;
myForm.Controls.Add(c);
}
First simplify
int totalCount = 1024; //16*64
const int shapeWidth =20;
const int shapeHeight = 20;
for (int j = 0; j < totalCount; j++)
{
OvalShape ovl = new OvalShape();
ovl.Width = shapeWidth;
ovl.Height = shapeHeight;
ovl.FillStyle = FillStyle.Solid;
ovl.FillColor = Color.Green;
ovalShape.Add(ovl);
}
After pickup your drawing area and decide how much shapes per row you would like to have.
So some hypothetical code could look like this:
int shapesPerRowCount = 5;
int yPos = 0;
for(int i=0;i<ovalShape.Count;i++)
{
if(i % shapesPerRowCount == 0) //reach end of the row, so offset Y position by Height
yPos += shapeHeight;
int xPos = i*shapeWidth;
DrawShapeAtPos(ovalShape[i], xPos, yPos); //some special function that draws the shape
}
A very generic code, but just to provide you an idea.
If it's not what you're searching for, please clarify.
Related
I want to create a program that will create the picturebox to the number that the user enters.
I use the following code.
int i,j,X = 395, Y = 7, S = 200 / int.Parse(textBox2.Text), C = int.Parse(textBox2.Text),CCC = 0;
PPP = new PictureBox[C];
for (i = 0; i < C; i++)
{
X = X + 5;
for (j = 0; j < C; j++)
{
Y = Y + 5;
PPP[CCC] = new PictureBox()
{
BackColor = Color.OrangeRed,
Size = new Size(S, S),
Location = new Point(X, Y)
};
Controls.Add(PPP[CCC]);
}
CCC++;
}
Thanks.
Part of the problem is that you have to update X and Y so your PictureBoxes are not drawn on top of each other.
This generates a picturebox
PictureBox[][] picturebox;
public void loadPictureBox()
{
string path = #"../../Images/Catelogue/"; //set pathing
string[] list = Directory.GetFiles(path, "*.jpg");
//pictureboxCatelogue = new PictureBox[list.Length];
//pictureboxCosplay = new PictureBox[list.Length];
picturebox = new PictureBox[4][];
for (int i = 0; i < 4; i++)
{
picturebox[i] = new PictureBox[list.Length];
int y = 85, temp = 220, run = 0;
for (int index = 13; index < list.Length; index++) // loads all pictures and create pictureboxes
{
picturebox[i][index] = new PictureBox();
picturebox[i][index].Image = Image.FromFile(path + index + ".jpg");
this.Controls.Add(picturebox[i][index]);
temp = temp + 200;
if (index % 4 == 0)
{
if (run != 0)
y = y + 200;
run++;
temp = 220;
}
picturebox[i][index].Location = new Point(temp, y);
picturebox[i][index].Size = new Size(180, 180);
picturebox[i][index].Name = Convert.ToString(index);
picturebox[i][index].SizeMode = PictureBoxSizeMode.Zoom;
picturebox[i][index].BackColor = Color.FromArgb(35, 35, 35);
picturebox[i][index].Click += new System.EventHandler(PictureBox_Click);
}
}
}
I'm trying to hide a jagged array which is a picturebox in winsform c#, but i keep getting an error, is hiding a jagged array possible? This is the code that i'm having trouble with.
for (int i = 0; i < picturebox.Length; i++)
{
picturebox[0][i].Hide();
}
This is the error i get
ERROR : A first chance exception of type 'System.NullReferenceException' occurred in APPD Assignment 2.exe (Additional information: Object reference not set to an instance of an object.)
Aren't you using the wrong length here?
for (int i = 0; i < picturebox.Length; i++)
Should be
for (int i = 0; i < picturebox[0].Length; i++)
When you load the pictureboxes, you're only starting at index 13, so you either need to start the hide loop at 13, or check for null.
for (int i = 13; i < picturebox[0].Length; i++)
{ ... }
or
for (int i = 0; i < picturebox[0].Length; i++)
{
if (picturebox[0][i] != null)
{
picturebox[0][i].Hide();
}
}
private Button[,] arrButton = new Button[10, 10];
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
arrButton[i, j] = new Button();//getting System.IndexOutOfRangeException
arrButton[i, j].Size = new Size(30, 30);
arrButton[i, j].Location = new Point(i * 30, j * 30);
arrButton[i, j].Click += new EventHandler(arrButton_Click);
this.Controls.Add(arrButton[i, j]);
}
}
this.ClientSize = new Size(300, 300);
After create, array button come up top left corner on form.
how to get array button to a place on form
#choz comment is correct, but a couple things to also consider.
Put the row value and column value in constant variables and use the variables, instead of directly using a number repeatedly.
Example:
private const ROW = 10;
private const COL = 10;
private Button[,] arrButton = new Button[ROW, COL];
...
for (int i = 0; i < ROW; i++)
{
// Change from your code -|
// |----------
// V
for (int j = 0; j < COL; j++)
{
// Create your buttons
}
}
If you are going to use constant numerals, then reference the GetUpperBound() from your array to know the last index value of each dimension.
Example:
private Button[,] arrButton = new Button[10, 10];
...
// GetUpperBound(0) = last index of rows (9 in this case)
for (int i = 0; i <= arrButton.GetUpperBound(0); i++)
{
// Change from your code -|
// |----------
// V GetUpperBound(1) = last index of columns (9 in this case)
for (int j = 0; j <= arrButton.GetUpperBound(1); j++)
{
// Create your buttons
}
}
Syntax error! Your second loop should be:
for (int j = 0; j < 10; j++)
You put "i" instead of "j",
Normally, when you get an System.IndexOutOfRangeException. The debugger error is telling you that the loop or loops you are using are counting the elements more than you specific. Check The count of elements you tinkering with.
I think you are making a mistake in inner loop. Can you please paste this and try to run:
private Button[,] arrButton = new Button[10, 10];
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)//Changed i to j
{
arrButton[i, j] = new Button();
arrButton[i, j].Size = new Size(30, 30);
arrButton[i, j].Location = new Point(i * 30, j * 30);
arrButton[i, j].Click += new EventHandler(arrButton_Click);
this.Controls.Add(arrButton[i, j]);
}
}
this.ClientSize = new Size(300, 300);
Ive been working on a code that takes an image, turns it into grayscale, and then does image manipulation depending on which button is pressed. When a button is pressed (ex. Average 3x3, Prewitt 5x5), it calls a 2D Multiplication function, which loops over the grayscale image, while looping over the kernel, adding all the values in the matrix. If any value is over 255, it sets it to 255. Then using the SetPixel on a temporary bitmap variable, which is finally put into the picturebox. When i run the program, I select an image and it shows it (as grayscale), but after choosing one of the filters, the program freezes for around 30 seconds, and then nothing changes, no filter is applied. Ive tried debugging and i cant seem to locate what the problem is!
EDIT: The initial question has been solved( I had to refresh the picturebox for the new image to show properly.
But i am facing another problem here with regards to the prewitt kernel.
i get this error
"Additional information: Value of '-6' is not valid for 'red'. 'red' should be greater than or equal to 0 and less than or equal to 255."
And i am not sure what to change in my code to fix this.
Initializing:
public partial class Form1 : Form
{
private Image img;
Bitmap grayscaleimage;
double[][] AVGKernel = new double[11][];
double[][] PrewittKernel = new double[11][];
int[] AVGKernal1DH = new int[11];
int[] AVGKernal1DV = new int[11];
Bitmap tempBitmap;
public Form1()
{
InitializeComponent();
for (int i = 0; i < 11; i++)
{
AVGKernel[i] = new double[11];
PrewittKernel[i] = new double[11];
for (int j = 0; j < 11; j++)
{
AVGKernel[i][j] = 0;
PrewittKernel[i][j] = 0;
AVGKernal1DH[j] = 0;
AVGKernal1DV[j] = 0;
}
}
}
The open button and turning the picture into grayscale:
private void OpenImageButton(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
this.img = Image.FromFile(openFileDialog.FileName);
grayscaleimage = new Bitmap(img);
int rgb;
Color c;
for (int y = 0; y < grayscaleimage.Height; y++)
for (int x = 0; x < grayscaleimage.Width; x++)
{
c = grayscaleimage.GetPixel(x, y);
rgb = (int)((c.R + c.G + c.B) / 3);
grayscaleimage.SetPixel(x, y, Color.FromArgb(rgb, rgb, rgb));
}
this.pictureBox1.BackgroundImage = grayscaleimage;
pictureBox1.BackgroundImageLayout = ImageLayout.Zoom;
}
}
an example of the many buttons available:
private void button5_Click(object sender, EventArgs e)
{
AVGKernel[0][0] = 1; AVGKernel[0][1] = 1; AVGKernel[0][2] = 1; AVGKernel[0][3] = 1; AVGKernel[0][4] = 1;
AVGKernel[1][0] = 1; AVGKernel[1][1] = 1; AVGKernel[1][2] = 1; AVGKernel[1][3] = 1; AVGKernel[1][4] = 1;
AVGKernel[2][0] = 1; AVGKernel[2][1] = 1; AVGKernel[2][2] = 1; AVGKernel[2][3] = 1; AVGKernel[2][4] = 1;
AVGKernel[3][0] = 1; AVGKernel[3][1] = 1; AVGKernel[3][2] = 1; AVGKernel[3][3] = 1; AVGKernel[3][4] = 1;
AVGKernel[4][0] = 1; AVGKernel[4][1] = 1; AVGKernel[4][2] = 1; AVGKernel[4][3] = 1; AVGKernel[4][4] = 1;
kernal2DMultiplication(AVGKernel, 5);
this.pictureBox1.BackgroundImage = tempBitmap;
}
Prewitt 5x5 kernel
private void button13_Click(object sender, EventArgs e)
{
PrewittKernel[0][0] = 2; PrewittKernel[0][1] = 1; PrewittKernel[0][2] = 0; PrewittKernel[0][3] = -1; PrewittKernel[0][4] = -2;
PrewittKernel[1][0] = 2; PrewittKernel[1][1] = 1; PrewittKernel[1][2] = 0; PrewittKernel[1][3] = -1; PrewittKernel[1][4] = -2;
PrewittKernel[2][0] = 2; PrewittKernel[2][1] = 1; PrewittKernel[2][2] = 0; PrewittKernel[2][3] = -1; PrewittKernel[2][4] = -2;
PrewittKernel[3][0] = 2; PrewittKernel[3][1] = 1; PrewittKernel[3][2] = 0; PrewittKernel[3][3] = -1; PrewittKernel[3][4] = -2;
PrewittKernel[4][0] = 2; PrewittKernel[4][1] = 1; PrewittKernel[4][2] = 0; PrewittKernel[4][3] = -1; PrewittKernel[4][4] = -2;
kernal2DMultiplication(PrewittKernel, 5);
this.pictureBox1.BackgroundImage = tempBitmap;
this.pictureBox1.Refresh();
}
and finally, the function being called:
private void kernal2DMultiplication(double[][] kernel, int size)
{
tempBitmap = grayscaleimage;
double nrgb = 0;
for (int i = 0; i < grayscaleimage.Width - size / 2; i++)
{
for (int j = 0; j < grayscaleimage.Height - size / 2; j++)
{
if (i >= size / 2 && j >= size / 2)
{
for (int k = 0; k < size; k++)
for (int l = 0; l < size; l++)
nrgb += grayscaleimage.GetPixel(i + k - (size / 2), j + l - (size / 2)).R * kernel[k][l];
nrgb = nrgb / (size * size);
if (nrgb > 255)
nrgb = 255;
tempBitmap.SetPixel(i, j, Color.FromArgb((int)nrgb, (int)nrgb, (int)nrgb));
}
}
}
}
The problem is that you are modifying the BackgroundImage bitmap in-place rather than copying, modifying the copy, and then setting the copy to be the BackgroundImage:
this.pictureBox1.BackgroundImage = grayscaleimage; // initially
tempBitmap = grayscaleimage;
// Make changes to tempBitmap
this.pictureBox1.BackgroundImage = tempBitmap; // actually still the same pointer
The BackgroundImage setter is not forcing a redraw of the control in this case. To force this yourself, call Refresh():
this.pictureBox1.Refresh();
To improver performance, look into replacing multiple calls to SetPixel with a single call to LockBits. See e.g. here.
I'm trying this code:
arrList = new List<CheckBox>();
for (int j = 0; j < 20; j++)
{
CheckBox check = new CheckBox();
arrList.Add(check);
}
CheckBox[] cb = arrList.ToArray();
for (int i = 0; i < 20; i++)
{
cb[i].Text = "sometext";
cb[i].Location = new System.Drawing.Point(10, 15 + i * 20);
cb[i].BackColor = System.Drawing.Color.Silver;
cb[i].Name = "somename";
cb[i].Size = new System.Drawing.Size(59, 17);
cb[i].Checked = true;
groupBox1.Controls.Add(cb[i]);
}
How can I add a vertical scroll bar there? (maybe I should use something instead of groupbox?)
You could use a Panel control and set it's AutoScroll property to True